diff --git a/.gitignore b/.gitignore
index 89426b7bff..bc65d666b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,10 @@ menu/driverspzarch.c
.pc
/media/shaders_glsl/
/obj-w32/
+.cproject
+.settings
+libretro-super
+run.sh
# Wii U
*.depend
diff --git a/.project b/.project
index 871dee54b0..b5f91e201f 100644
--- a/.project
+++ b/.project
@@ -5,7 +5,23 @@
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
diff --git a/CHANGES.md b/CHANGES.md
index 3674186a41..c9ed1b06de 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,8 +1,12 @@
# 1.7.4 (future)
- ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu.
- ANDROID: Powerstate/battery level support.
+- CHEEVOS: Fix crash when scrolling Achievement List while Unofficial Achievements enabled (#6732).
+- CHEEVOS: Added hitcounts support for PauseIf/ResetIf (#6817).
- COMMON: Automatically hide "Configuration Override options" in Quick Menu.
- COMMON: Small Bugfix to not trigger savestate code when pressing Reset.
+- COMMON: Added libsixel video driver.
+- EMSCRIPTEN: Fix Game Focus Toggle.
- HID/OSX: Fix to set hid device registration deterministic (#6497), to address issue #6640 re-adding dynamic device registration.
- LOCALIZATION: Update Italian translation.
- LOCALIZATION: Update Japanese translation.
@@ -14,8 +18,10 @@
- MIDI: Add a Windows driver for MIDI, based on winmm.
- MENU/QT/WIMP: QT QSlider styling for Dark Theme.
- MENU/QT/WIMP: Remove button ghostly inside highlighting.
-- METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13. Works with RGUI right now.
+- METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13.
+- METAL: Supports XMB/MaterialUI, has a menu display driver. Has a font rendering driver.
- METAL/SLANG: Slang shaders should be compatible with Metal video driver.
+- QNX: Fix Game Focus Toggle.
- PS3: Add audio mixer support for FLAC and MP3.
- PSP: Use proper button labels, fix inverted R-Stick Y axis.
- REMAPS: Fix the way offsets are calculated for keyboard remapping.
@@ -24,9 +30,14 @@
- VULKAN: Fix two validation errors.
- VULKAN: Try to avoid creating swapchains redundantly. Should fix black screen and having to alt tab out of window again to get display working on Nvidia GPUs (Windows).
- VULKAN/OSX: Initial MoltenVK support. Not enabled yet, several MoltenVK bugs should be fixed first before we can have it fully working.
+- WINDOWS/DINPUT: Add rumble support.
+- WINDOWS/DINPUT: Fix Game Focus Toggle.
+- WINDOWS/RAWINPUT: Fix Game Focus Toggle.
+- X11: Fix Game Focus Toggle.
- WII: Change deflicker setting to work in 480p or higher, and always enables vfilter so that the user can easily change brightness.
- WIIU: Fix out-of-bounds rendering bug
- WIIU: Implement UDP broadcast network logging on Wii U.
+- WIIU: Audio should no longer clip.
# 1.7.3
- AUDIO: Audio mixer supports FLAC/MP3 file types now!
diff --git a/Makefile.common b/Makefile.common
index bb29f29791..b2c83a60b8 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -743,11 +743,16 @@ ifeq ($(HW_CONTEXT_MENU_DRIVERS), 1)
ifeq ($(HAVE_XMB),)
HAVE_XMB = 1
endif
+
+ ifeq ($(HAVE_STRIPES),)
+ HAVE_STRIPES = 1
+ endif
else
HAVE_ZARCH ?= 0
HAVE_MATERIALUI ?= 0
#HAVE_NUKLEAR ?= 0
HAVE_XMB ?= 0
+ HAVE_STRIPES ?= 0
endif
ifeq ($(HAVE_RGUI), 1)
@@ -779,6 +784,12 @@ ifeq ($(HAVE_XMB), 1)
HAVE_MENU_COMMON = 1
endif
+ifeq ($(HAVE_STRIPES), 1)
+ OBJ += menu/drivers/stripes.o
+ DEFINES += -DHAVE_STRIPES
+ HAVE_MENU_COMMON = 1
+endif
+
ifeq ($(HAVE_LAKKA), 1)
DEFINES += -DHAVE_LAKKA
endif
@@ -1046,6 +1057,18 @@ ifeq ($(HAVE_CACA), 1)
endif
endif
+ifeq ($(HAVE_SIXEL), 1)
+ DEFINES += -DHAVE_SIXEL
+ CFLAGS += -I/usr/include/sixel
+ OBJ += gfx/drivers/sixel_gfx.o gfx/drivers_font/sixel_font.o \
+ gfx/drivers_context/sixel_ctx.o
+ LIBS += -lsixel
+
+ ifeq ($(HAVE_MENU_COMMON), 1)
+ OBJ += menu/drivers_display/menu_display_sixel.o
+ endif
+endif
+
ifeq ($(HAVE_PLAIN_DRM), 1)
OBJ += gfx/drivers/drm_gfx.o
CFLAGS += -I/usr/include/libdrm
@@ -1107,6 +1130,20 @@ endif
endif
endif
+ifeq ($(HAVE_METAL), 1)
+ DEFINES += -DHAVE_METAL
+ OBJ += gfx/common/metal/Context.o \
+ gfx/common/metal/Filter.o \
+ gfx/common/metal/RendererCommon.o \
+ gfx/common/metal/View.o \
+ gfx/common/metal/TexturedView.o \
+ gfx/common/metal/MenuDisplay.o \
+ gfx/common/metal_common.o \
+ gfx/drivers/metal.o \
+ menu/drivers_display/menu_display_metal.o \
+ gfx/drivers_font/metal_raster_font.o
+endif
+
ifeq ($(HAVE_MPV), 1)
OBJ += cores/libretro-mpv/mpv-libretro.o
DEFINES += -I$(DEPS_DIR) -DHAVE_MPV
diff --git a/audio/drivers/wiiu_audio.c b/audio/drivers/wiiu_audio.c
index 437ee310bf..0ea9106206 100644
--- a/audio/drivers/wiiu_audio.c
+++ b/audio/drivers/wiiu_audio.c
@@ -84,7 +84,7 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency,
u16 setup_buf[0x30] = {0};
setup_buf[0x25] = 2; /* we request 2 channels */
AXInitParams init = {AX_INIT_RENDERER_48KHZ, 0, 0};
- AXVoiceVeData ve = {0xF000, 0};
+ AXVoiceVeData ve = {0x8000, 0};
ax_audio_t* ax = (ax_audio_t*)calloc(1, sizeof(ax_audio_t));
if (!ax)
diff --git a/command.c b/command.c
index 23fa89a565..5775e4f6a2 100644
--- a/command.c
+++ b/command.c
@@ -1051,8 +1051,11 @@ static void command_event_deinit_core(bool reinit)
cheevos_unload();
#endif
+ RARCH_LOG("Unloading game..\n");
core_unload_game();
+ RARCH_LOG("Unloading core..\n");
core_unload();
+ RARCH_LOG("Unloading core symbols..\n");
core_uninit_symbols();
if (reinit)
@@ -1395,7 +1398,6 @@ static bool command_event_save_config(
static bool command_event_save_core_config(void)
{
char msg[128];
- bool ret = false;
bool found_path = false;
bool overrides_active = false;
const char *core_path = NULL;
@@ -1502,7 +1504,7 @@ static bool command_event_save_core_config(void)
free(config_dir);
free(config_name);
free(config_path);
- return ret;
+ return true;
}
/**
@@ -1835,14 +1837,21 @@ bool command_event(enum event_command cmd, void *data)
if (cheevos_hardcore_active)
return false;
#endif
-
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_UNDO_LOAD_STATE:
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_UNDO_SAVE_STATE:
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_RESIZE_WINDOWED_SCALE:
- return command_event_resize_windowed_scale();
+ if (!command_event_resize_windowed_scale())
+ return false;
+ break;
case CMD_EVENT_MENU_TOGGLE:
#ifdef HAVE_MENU
if (menu_driver_is_alive())
@@ -1883,7 +1892,9 @@ bool command_event(enum event_command cmd, void *data)
configuration_set_int(settings, settings->ints.state_slot, new_state_slot);
}
}
- return command_event_main_state(cmd);
+ if (!command_event_main_state(cmd))
+ return false;
+ break;
case CMD_EVENT_SAVE_STATE_DECREMENT:
{
settings_t *settings = config_get_ptr();
@@ -1933,7 +1944,9 @@ bool command_event(enum event_command cmd, void *data)
}
break;
case CMD_EVENT_QUIT:
- return retroarch_main_quit();
+ if (!retroarch_main_quit())
+ return false;
+ break;
case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE:
#ifdef HAVE_CHEEVOS
cheevos_toggle_hardcore_mode();
@@ -1997,7 +2010,7 @@ TODO: Add a setting for these tweaks */
if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
#endif
{
- state_manager_event_init((unsigned)settings->rewind_buffer_size);
+ state_manager_event_init((unsigned)settings->sizes.rewind_buffer_size);
}
}
}
@@ -2043,9 +2056,13 @@ TODO: Add a setting for these tweaks */
break;
case CMD_EVENT_AUDIO_STOP:
midi_driver_set_all_sounds_off();
- return audio_driver_stop();
+ if (!audio_driver_stop())
+ return false;
+ break;
case CMD_EVENT_AUDIO_START:
- return audio_driver_start(rarch_ctl(RARCH_CTL_IS_SHUTDOWN, NULL));
+ if (!audio_driver_start(rarch_ctl(RARCH_CTL_IS_SHUTDOWN, NULL)))
+ return false;
+ break;
case CMD_EVENT_AUDIO_MUTE_TOGGLE:
{
bool audio_mute_enable = *(audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE));
@@ -2630,14 +2647,13 @@ TODO: Add a setting for these tweaks */
command_event(CMD_EVENT_REMOTE_DEINIT, NULL);
input_driver_init_remote();
break;
-
case CMD_EVENT_MAPPER_DEINIT:
input_driver_deinit_mapper();
break;
case CMD_EVENT_MAPPER_INIT:
command_event(CMD_EVENT_MAPPER_DEINIT, NULL);
input_driver_init_mapper();
- break;
+ break;
case CMD_EVENT_LOG_FILE_DEINIT:
retro_main_log_file_deinit();
break;
@@ -2646,8 +2662,10 @@ TODO: Add a setting for these tweaks */
const char *path = (const char*)data;
if (string_is_empty(path))
return false;
- return command_event_disk_control_append_image(path);
+ if (!command_event_disk_control_append_image(path))
+ return false;
}
+ break;
case CMD_EVENT_DISK_EJECT_TOGGLE:
{
rarch_system_info_t *info = runloop_get_system_info();
@@ -2754,10 +2772,8 @@ TODO: Add a setting for these tweaks */
}
break;
case CMD_EVENT_UI_COMPANION_TOGGLE:
- {
- ui_companion_driver_toggle(true);
- break;
- }
+ ui_companion_driver_toggle(true);
+ break;
case CMD_EVENT_GAME_FOCUS_TOGGLE:
{
static bool game_focus_state = false;
diff --git a/config.def.h b/config.def.h
index 546e7bebfd..189449b793 100644
--- a/config.def.h
+++ b/config.def.h
@@ -524,6 +524,9 @@ static const bool rewind_enable = false;
* 15-20MB per minute. Very game dependant. */
static const unsigned rewind_buffer_size = 20 << 20; /* 20MiB */
+/* The amount of MB to increase/decrease the rewind_buffer_size when it is changed via the UI. */
+static const unsigned rewind_buffer_size_step = 10; /* 10MB */
+
/* How many frames to rewind at a time. */
static const unsigned rewind_granularity = 1;
@@ -701,12 +704,16 @@ static const unsigned midi_volume = 100;
static const bool sustained_performance_mode = false;
#if defined(ANDROID)
-#if defined(ANDROID_ARM)
+#if defined(ANDROID_ARM_V7)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/armeabi-v7a/";
+#elif defined(ANDROID_ARM)
+static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/armeabi/";
#elif defined(ANDROID_AARCH64)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/arm64-v8a/";
#elif defined(ANDROID_X86)
static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/x86/";
+#elif defined(ANDROID_X64)
+static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/android/latest/x86_64/";
#else
static char buildbot_server_url[] = "";
#endif
diff --git a/configuration.c b/configuration.c
index 13da1997f1..63e3d29d85 100644
--- a/configuration.c
+++ b/configuration.c
@@ -92,6 +92,16 @@ struct config_uint_setting
enum rarch_override_setting override;
};
+struct config_size_setting
+{
+ const char *ident;
+ size_t *ptr;
+ bool def_enable;
+ size_t def;
+ bool handle;
+ enum rarch_override_setting override;
+};
+
struct config_float_setting
{
const char *ident;
@@ -125,6 +135,7 @@ enum video_driver_enum
{
VIDEO_GL = 0,
VIDEO_VULKAN,
+ VIDEO_METAL,
VIDEO_DRM,
VIDEO_XVIDEO,
VIDEO_SDL,
@@ -273,6 +284,7 @@ enum menu_driver_enum
MENU_XUI,
MENU_MATERIALUI,
MENU_XMB,
+ MENU_STRIPES,
MENU_NUKLEAR,
MENU_NULL
};
@@ -291,6 +303,8 @@ enum midi_driver_enum
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
+#elif defined(HAVE_METAL)
+static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
#elif defined(GEKKO)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
#elif defined(WIIU)
@@ -515,6 +529,8 @@ static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL;
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XUI;
#elif defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE)
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI;
+#elif defined(HAVE_STRIPES) && !defined(_XBOX)
+static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_STRIPES;
#elif defined(HAVE_XMB) && !defined(_XBOX)
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XMB;
#elif defined(HAVE_RGUI)
@@ -547,6 +563,9 @@ static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
#define SETTING_UINT(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_uint_setting, handle_setting)
+#define SETTING_SIZE(key, configval, default_enable, default_setting, handle_setting) \
+ GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_size_setting, handle_setting)
+
#define SETTING_PATH(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_path_setting, handle_setting)
@@ -711,6 +730,8 @@ const char *config_get_default_video(void)
return "gl";
case VIDEO_VULKAN:
return "vulkan";
+ case VIDEO_METAL:
+ return "metal";
case VIDEO_DRM:
return "drm";
case VIDEO_WII:
@@ -1008,6 +1029,8 @@ const char *config_get_default_menu(void)
return "glui";
case MENU_XMB:
return "xmb";
+ case MENU_STRIPES:
+ return "stripes";
case MENU_NUKLEAR:
return "nuklear";
case MENU_NULL:
@@ -1503,6 +1526,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false);
SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false);
SETTING_UINT("rewind_granularity", &settings->uints.rewind_granularity, true, rewind_granularity, false);
+ SETTING_UINT("rewind_buffer_size_step", &settings->uints.rewind_buffer_size_step, true, rewind_buffer_size_step, false);
SETTING_UINT("autosave_interval", &settings->uints.autosave_interval, true, autosave_interval, false);
SETTING_UINT("libretro_log_level", &settings->uints.libretro_log_level, true, libretro_log_level, false);
SETTING_UINT("keyboard_gamepad_mapping_type",&settings->uints.input_keyboard_gamepad_mapping_type, true, 1, false);
@@ -1579,6 +1603,18 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
return tmp;
}
+static struct config_size_setting *populate_settings_size(settings_t *settings, int *size)
+{
+ unsigned count = 0;
+ struct config_size_setting *tmp = (struct config_size_setting*)malloc((*size + 1) * sizeof(struct config_size_setting));
+
+ SETTING_SIZE("rewind_buffer_size", &settings->sizes.rewind_buffer_size, true, rewind_buffer_size, false);
+
+ *size = count;
+
+ return tmp;
+}
+
static struct config_int_setting *populate_settings_int(settings_t *settings, int *size)
{
unsigned count = 0;
@@ -1614,6 +1650,7 @@ static void config_set_defaults(void)
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
const char *def_video = config_get_default_video();
const char *def_audio = config_get_default_audio();
const char *def_audio_resampler = config_get_default_audio_resampler();
@@ -1633,6 +1670,7 @@ static void config_set_defaults(void)
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
if (bool_settings && (bool_settings_size > 0))
{
@@ -1667,6 +1705,17 @@ static void config_set_defaults(void)
free(uint_settings);
}
+ if (size_settings && (size_settings_size > 0))
+ {
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ if (size_settings[i].def_enable)
+ *size_settings[i].ptr = size_settings[i].def;
+ }
+
+ free(size_settings);
+ }
+
if (float_settings && (float_settings_size > 0))
{
for (i = 0; i < (unsigned)float_settings_size; i++)
@@ -1758,8 +1807,6 @@ static void config_set_defaults(void)
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, settings->floats.audio_volume);
audio_set_float(AUDIO_ACTION_MIXER_VOLUME_GAIN, settings->floats.audio_mixer_volume);
- settings->rewind_buffer_size = rewind_buffer_size;
-
#ifdef HAVE_LAKKA
settings->bools.ssh_enable = filestream_exists(LAKKA_SSH_PATH);
settings->bools.samba_enable = filestream_exists(LAKKA_SAMBA_PATH);
@@ -2357,6 +2404,7 @@ static bool check_shader_compatibility(enum file_path_enum enum_idx)
settings_t *settings = config_get_ptr();
if (string_is_equal(settings->arrays.video_driver, "vulkan") ||
+ string_is_equal(settings->arrays.video_driver, "metal") ||
string_is_equal(settings->arrays.video_driver, "d3d11") ||
string_is_equal(settings->arrays.video_driver, "d3d12") ||
string_is_equal(settings->arrays.video_driver, "gx2"))
@@ -2457,12 +2505,14 @@ static bool config_load_file(const char *path, bool set_defaults,
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
struct config_array_setting *array_settings = populate_settings_array (settings, &array_settings_size);
struct config_path_setting *path_settings = populate_settings_path (settings, &path_settings_size);
@@ -2587,6 +2637,23 @@ static bool config_load_file(const char *path, bool set_defaults,
*uint_settings[i].ptr = tmp;
}
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ size_t tmp = 0;
+ if (config_get_size_t(conf, size_settings[i].ident, &tmp))
+ *size_settings[i].ptr = tmp ;
+ /* Special case for rewind_buffer_size - need to convert low values to what they were
+ * intended to be based on the default value in config.def.h
+ * If the value is less than 10000 then multiple by 1MB because if the retroarch.cfg
+ * file contains rewind_buffer_size = "100" then that ultimately gets interpreted as
+ * 100MB, so ensure the internal values represent that.*/
+ if ( strcmp(size_settings[i].ident, "rewind_buffer_size") == 0 ) {
+ if ( *size_settings[i].ptr < 10000) {
+ *size_settings[i].ptr = *size_settings[i].ptr * 1024 * 1024 ;
+ }
+ }
+ }
+
for (i = 0; i < MAX_USERS; i++)
{
char buf[64];
@@ -2618,13 +2685,6 @@ static bool config_load_file(const char *path, bool set_defaults,
CONFIG_GET_INT_BASE(conf, settings, uints.led_map[i], buf);
}
- {
- /* ugly hack around C89 not allowing mixing declarations and code */
- int buffer_size = 0;
- if (config_get_int(conf, "rewind_buffer_size", &buffer_size))
- settings->rewind_buffer_size = buffer_size * UINT64_C(1000000);
- }
-
/* Hexadecimal settings */
@@ -3948,6 +4008,7 @@ bool config_save_file(const char *path)
struct config_bool_setting *bool_settings = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
+ struct config_size_setting *size_settings = NULL;
struct config_float_setting *float_settings = NULL;
struct config_array_setting *array_settings = NULL;
struct config_path_setting *path_settings = NULL;
@@ -3957,6 +4018,7 @@ bool config_save_file(const char *path)
int float_settings_size = sizeof(settings->floats)/ sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays)/ sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
@@ -3973,6 +4035,7 @@ bool config_save_file(const char *path)
bool_settings = populate_settings_bool (settings, &bool_settings_size);
int_settings = populate_settings_int (settings, &int_settings_size);
uint_settings = populate_settings_uint (settings, &uint_settings_size);
+ size_settings = populate_settings_size (settings, &size_settings_size);
float_settings = populate_settings_float (settings, &float_settings_size);
array_settings = populate_settings_array (settings, &array_settings_size);
path_settings = populate_settings_path (settings, &path_settings_size);
@@ -4050,6 +4113,18 @@ bool config_save_file(const char *path)
free(uint_settings);
}
+ if (size_settings && (size_settings_size > 0))
+ {
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ if (!size_settings[i].override ||
+ !retroarch_override_setting_is_set(size_settings[i].override, NULL))
+ config_set_int(conf,
+ size_settings[i].ident,
+ *size_settings[i].ptr);
+
+ free(size_settings);
+ }
+
for (i = 0; i < MAX_USERS; i++)
{
char cfg[64];
@@ -4169,8 +4244,10 @@ bool config_save_overrides(int override_type)
struct config_bool_setting *bool_overrides = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
+ struct config_size_setting *size_settings = NULL;
struct config_int_setting *int_overrides = NULL;
struct config_uint_setting *uint_overrides = NULL;
+ struct config_size_setting *size_overrides = NULL;
struct config_float_setting *float_settings = NULL;
struct config_float_setting *float_overrides= NULL;
struct config_array_setting *array_settings = NULL;
@@ -4187,6 +4264,7 @@ bool config_save_overrides(int override_type)
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
int int_settings_size = sizeof(settings->ints) / sizeof(settings->ints.placeholder);
int uint_settings_size = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
+ int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
rarch_system_info_t *system = runloop_get_system_info();
@@ -4255,6 +4333,10 @@ bool config_save_overrides(int override_type)
tmp_i = sizeof(settings->uints) / sizeof(settings->uints.placeholder);
uint_overrides = populate_settings_uint (overrides, &tmp_i);
+ size_settings = populate_settings_size(settings, &size_settings_size);
+ tmp_i = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
+ size_overrides = populate_settings_size (overrides, &tmp_i);
+
float_settings = populate_settings_float(settings, &float_settings_size);
tmp_i = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
float_overrides = populate_settings_float(overrides, &tmp_i);
@@ -4307,6 +4389,18 @@ bool config_save_overrides(int override_type)
(*uint_overrides[i].ptr));
}
}
+ for (i = 0; i < (unsigned)size_settings_size; i++)
+ {
+ if ((*size_settings[i].ptr) != (*size_overrides[i].ptr))
+ {
+ RARCH_LOG(" original: %s=%d\n",
+ size_settings[i].ident, (*size_settings[i].ptr));
+ RARCH_LOG(" override: %s=%d\n",
+ size_overrides[i].ident, (*size_overrides[i].ptr));
+ config_set_int(conf, size_overrides[i].ident,
+ (*size_overrides[i].ptr));
+ }
+ }
for (i = 0; i < (unsigned)float_settings_size; i++)
{
if ((*float_settings[i].ptr) != (*float_overrides[i].ptr))
@@ -4423,6 +4517,8 @@ bool config_save_overrides(int override_type)
free(int_settings);
if (uint_settings)
free(uint_settings);
+ if (size_settings)
+ free(size_settings);
if (int_overrides)
free(int_overrides);
if (uint_overrides)
diff --git a/configuration.h b/configuration.h
index db968639f5..8955319959 100644
--- a/configuration.h
+++ b/configuration.h
@@ -348,6 +348,7 @@ typedef struct settings
unsigned content_history_size;
unsigned libretro_log_level;
unsigned rewind_granularity;
+ unsigned rewind_buffer_size_step;
unsigned autosave_interval;
unsigned network_cmd_port;
unsigned network_remote_base_port;
@@ -411,6 +412,12 @@ typedef struct settings
unsigned midi_volume;
} uints;
+ struct
+ {
+ size_t placeholder;
+ size_t rewind_buffer_size;
+ } sizes;
+
struct
{
char placeholder;
@@ -509,7 +516,6 @@ typedef struct settings
video_viewport_t video_viewport_custom;
- size_t rewind_buffer_size;
} settings_t;
/**
diff --git a/core_impl.c b/core_impl.c
index 7c2585a0c2..f1516fab7c 100644
--- a/core_impl.c
+++ b/core_impl.c
@@ -290,6 +290,8 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info)
bool contentless = false;
bool is_inited = false;
+ video_driver_set_cached_frame_ptr(NULL);
+
#ifdef HAVE_RUNAHEAD
set_load_content_info(load_info);
clear_controller_port_map();
@@ -373,12 +375,16 @@ bool core_get_system_av_info(struct retro_system_av_info *av_info)
bool core_reset(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_reset();
return true;
}
bool core_init(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_init();
current_core.inited = true;
return true;
@@ -386,6 +392,8 @@ bool core_init(void)
bool core_unload(void)
{
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_deinit();
return true;
}
@@ -396,9 +404,12 @@ bool core_unload_game(void)
video_driver_free_hw_context();
audio_driver_stop();
+ video_driver_set_cached_frame_ptr(NULL);
+
current_core.retro_unload_game();
current_core.game_loaded = false;
+
return true;
}
diff --git a/deps/SPIRV-Cross/CMakeLists.txt b/deps/SPIRV-Cross/CMakeLists.txt
index 9226afd46f..2849b6957d 100644
--- a/deps/SPIRV-Cross/CMakeLists.txt
+++ b/deps/SPIRV-Cross/CMakeLists.txt
@@ -93,6 +93,10 @@ spirv_cross_add_library(spirv-cross-cpp spirv_cross_cpp STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_cpp.cpp)
+spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.hpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.cpp)
+
spirv_cross_add_library(spirv-cross-msl spirv_cross_msl STATIC
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_msl.cpp)
@@ -110,7 +114,7 @@ target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options})
target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines})
install(TARGETS spirv-cross RUNTIME DESTINATION bin)
-target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-msl spirv-cross-util spirv-cross-core)
+target_link_libraries(spirv-cross spirv-cross-glsl spirv-cross-hlsl spirv-cross-cpp spirv-cross-reflect spirv-cross-msl spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-util spirv-cross-core)
target_link_libraries(spirv-cross-glsl spirv-cross-core)
target_link_libraries(spirv-cross-msl spirv-cross-glsl)
diff --git a/deps/SPIRV-Cross/README.md b/deps/SPIRV-Cross/README.md
index 5f92698602..d3c1a93a07 100644
--- a/deps/SPIRV-Cross/README.md
+++ b/deps/SPIRV-Cross/README.md
@@ -11,6 +11,7 @@ SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader
- Convert SPIR-V to readable, usable and efficient Metal Shading Language (MSL)
- Convert SPIR-V to readable, usable and efficient HLSL
- Convert SPIR-V to debuggable C++ [EXPERIMENTAL]
+ - Convert SPIR-V to a JSON reflection format [EXPERIMENTAL]
- Reflection API to simplify the creation of Vulkan pipeline layouts
- Reflection API to modify and tweak OpDecorations
- Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.
diff --git a/deps/SPIRV-Cross/main.cpp b/deps/SPIRV-Cross/main.cpp
index b309a82ac3..69bd135c1a 100644
--- a/deps/SPIRV-Cross/main.cpp
+++ b/deps/SPIRV-Cross/main.cpp
@@ -19,6 +19,7 @@
#include "spirv_glsl.hpp"
#include "spirv_hlsl.hpp"
#include "spirv_msl.hpp"
+#include "spirv_reflect.hpp"
#include
#include
#include
@@ -149,6 +150,22 @@ struct CLIParser
return val;
}
+ // Return a string only if it's not prefixed with `--`, otherwise return the default value
+ const char *next_value_string(const char *default_value)
+ {
+ if (!argc)
+ {
+ return default_value;
+ }
+
+ if (0 == strncmp("--", *argv, 2))
+ {
+ return default_value;
+ }
+
+ return next_string();
+ }
+
const char *next_string()
{
if (!argc)
@@ -461,6 +478,7 @@ struct CLIArguments
bool fixup = false;
bool yflip = false;
bool sso = false;
+ bool support_nonzero_baseinstance = true;
vector pls_in;
vector pls_out;
vector remaps;
@@ -481,6 +499,7 @@ struct CLIArguments
uint32_t iterations = 1;
bool cpp = false;
+ string reflect;
bool msl = false;
bool hlsl = false;
bool hlsl_compat = false;
@@ -512,6 +531,7 @@ static void print_help()
"\t[--msl]\n"
"\t[--msl-version ]\n"
"\t[--hlsl]\n"
+ "\t[--reflect]\n"
"\t[--shader-model]\n"
"\t[--hlsl-enable-compat]\n"
"\t[--separate-shader-objects]\n"
@@ -528,7 +548,8 @@ static void print_help()
"\t[--rename-interface-variable ]\n"
"\t[--set-hlsl-vertex-input-semantic ]\n"
"\t[--rename-entry-point ]\n"
- "\t[--combined-samplers-inherit-bindings]"
+ "\t[--combined-samplers-inherit-bindings]\n"
+ "\t[--no-support-nonzero-baseinstance]\n"
"\n");
}
@@ -663,6 +684,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
+ cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
@@ -737,6 +759,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--combined-samplers-inherit-bindings",
[&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
+ cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
+
cbs.default_handler = [&args](const char *value) { args.input = value; };
cbs.error_handler = [] { print_help(); };
@@ -757,8 +781,20 @@ static int main_inner(int argc, char *argv[])
return EXIT_FAILURE;
}
- unique_ptr compiler;
+ // Special case reflection because it has little to do with the path followed by code-outputting compilers
+ if (!args.reflect.empty())
+ {
+ CompilerReflection compiler(read_spirv_file(args.input));
+ compiler.set_format(args.reflect);
+ auto json = compiler.compile();
+ if (args.output)
+ write_string_to_file(args.output, json.c_str());
+ else
+ printf("%s", json.c_str());
+ return EXIT_SUCCESS;
+ }
+ unique_ptr compiler;
bool combined_image_samplers = false;
bool build_dummy_sampler = false;
@@ -895,6 +931,7 @@ static int main_inner(int argc, char *argv[])
opts.vulkan_semantics = args.vulkan_semantics;
opts.vertex.fixup_clipspace = args.fixup;
opts.vertex.flip_vert_y = args.yflip;
+ opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
compiler->set_common_options(opts);
// Set HLSL specific options.
diff --git a/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj b/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj
index 6040e2e116..d2287dcbe9 100644
--- a/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj
+++ b/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj
@@ -127,6 +127,7 @@
+
@@ -138,6 +139,7 @@
+
diff --git a/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj.filters b/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj.filters
index f853c08b5b..3ff2c29a58 100644
--- a/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj.filters
+++ b/deps/SPIRV-Cross/msvc/SPIRV-Cross.vcxproj.filters
@@ -24,6 +24,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -50,6 +53,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/comp/control-flow-hints.asm.comp b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
new file mode 100644
index 0000000000..142ef5efa8
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
@@ -0,0 +1,32 @@
+RWByteAddressBuffer bar : register(u0);
+RWByteAddressBuffer foo : register(u1);
+
+void comp_main()
+{
+ [unroll]
+ for (int _135 = 0; _135 < 16; )
+ {
+ bar.Store4(_135 * 16 + 0, asuint(asfloat(foo.Load4(_135 * 16 + 0))));
+ _135++;
+ continue;
+ }
+ [loop]
+ for (int _136 = 0; _136 < 16; )
+ {
+ bar.Store4((15 - _136) * 16 + 0, asuint(asfloat(foo.Load4(_136 * 16 + 0))));
+ _136++;
+ continue;
+ }
+ [branch]
+ if (asfloat(bar.Load(160)) > 10.0f)
+ {
+ foo.Store4(320, asuint(5.0f.xxxx));
+ }
+ foo.Store4(320, asuint(20.0f.xxxx));
+}
+
+[numthreads(1, 1, 1)]
+void main()
+{
+ comp_main();
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..5deae3a569
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,57 @@
+static const float _46[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
+static const float4 _76[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
+static const float4 _90[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
+
+static float FragColor;
+static int index;
+
+struct SPIRV_Cross_Input
+{
+ nointerpolation int index : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ float4 foobar[4] = _76;
+ float4 baz[4] = _76;
+ FragColor = _46[index];
+ if (index < 10)
+ {
+ FragColor += _46[index ^ 1];
+ }
+ else
+ {
+ FragColor += _46[index & 1];
+ }
+ bool _99 = index > 30;
+ if (_99)
+ {
+ FragColor += _76[index & 3].y;
+ }
+ else
+ {
+ FragColor += _76[index & 1].x;
+ }
+ if (_99)
+ {
+ foobar[1].z = 20.0f;
+ }
+ int _37 = index & 3;
+ FragColor += foobar[_37].z;
+ baz = _90;
+ FragColor += baz[_37].z;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ index = stage_input.index;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..5b894de831
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,31 @@
+Texture2D uShadow : register(t0);
+SamplerComparisonState _uShadow_sampler : register(s0);
+Texture2D uTexture : register(t1);
+SamplerComparisonState uSampler : register(s2);
+
+static float3 vUV;
+static float FragColor;
+
+struct SPIRV_Cross_Input
+{
+ float3 vUV : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ FragColor = uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z) + uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ vUV = stage_input.vUV;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..0d1e8cc534
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,28 @@
+static float4 gl_Position;
+static int gl_VertexIndex;
+static int gl_InstanceIndex;
+struct SPIRV_Cross_Input
+{
+ uint gl_VertexIndex : SV_VertexID;
+ uint gl_InstanceIndex : SV_InstanceID;
+};
+
+struct SPIRV_Cross_Output
+{
+ float4 gl_Position : SV_Position;
+};
+
+void vert_main()
+{
+ gl_Position = float(uint(gl_VertexIndex) + uint(gl_InstanceIndex)).xxxx;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ gl_VertexIndex = int(stage_input.gl_VertexIndex);
+ gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
+ vert_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.gl_Position = gl_Position;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/comp/globallycoherent.comp b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/comp/globallycoherent.comp
new file mode 100644
index 0000000000..1637727deb
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/comp/globallycoherent.comp
@@ -0,0 +1,16 @@
+globallycoherent RWByteAddressBuffer _29 : register(u3);
+ByteAddressBuffer _33 : register(t2);
+RWTexture2D uImageIn : register(u0);
+globallycoherent RWTexture2D uImageOut : register(u1);
+
+void comp_main()
+{
+ uImageOut[int2(9, 7)] = uImageIn[int2(9, 7)].x;
+ _29.Store(0, asuint(asfloat(_33.Load(0))));
+}
+
+[numthreads(1, 1, 1)]
+void main()
+{
+ comp_main();
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/array-lut-no-loop-variable.frag
index 8cb52f0a4d..3adf7d9852 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/array-lut-no-loop-variable.frag
@@ -15,11 +15,10 @@ struct SPIRV_Cross_Output
void frag_main()
{
- float lut[5] = _17;
for (int _46 = 0; _46 < 4; )
{
int _33 = _46 + 1;
- FragColor += lut[_33].xxxx;
+ FragColor += _17[_33].xxxx;
_46 = _33;
continue;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/constant-composites.frag
index 0514eef1ee..2613e1c2c5 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/constant-composites.frag
@@ -30,7 +30,7 @@ void frag_main()
lut = _16;
foos = _28;
FragColor = lut[_line].xxxx;
- FragColor += (foos[_line].a * (foos[1 - _line].a)).xxxx;
+ FragColor += (foos[_line].a * foos[1 - _line].a).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..aae0d39de2
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/lut-promotion.frag
@@ -0,0 +1,57 @@
+static const float _16[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
+static const float4 _60[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
+static const float4 _104[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
+
+static float FragColor;
+static int index;
+
+struct SPIRV_Cross_Input
+{
+ nointerpolation int index : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ FragColor = _16[index];
+ if (index < 10)
+ {
+ FragColor += _16[index ^ 1];
+ }
+ else
+ {
+ FragColor += _16[index & 1];
+ }
+ bool _63 = index > 30;
+ if (_63)
+ {
+ FragColor += _60[index & 3].y;
+ }
+ else
+ {
+ FragColor += _60[index & 1].x;
+ }
+ float4 foobar[4] = _60;
+ if (_63)
+ {
+ foobar[1].z = 20.0f;
+ }
+ int _91 = index & 3;
+ FragColor += foobar[_91].z;
+ float4 baz[4] = _60;
+ baz = _104;
+ FragColor += baz[_91].z;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ index = stage_input.index;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..12e0f5bd79
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-hlsl/frag/spec-constant-ternary.frag
@@ -0,0 +1,23 @@
+static const uint s = 10u;
+static const bool _13 = (s > 20u);
+static const uint _16 = _13 ? 30u : 50u;
+
+static float FragColor;
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ FragColor = float(_16);
+}
+
+SPIRV_Cross_Output main()
+{
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..9db6b5470d
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,69 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+constant float _46[16] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
+constant float4 _76[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+constant float4 _90[4] = {float4(20.0), float4(30.0), float4(50.0), float4(60.0)};
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ int index [[user(locn0)]];
+};
+
+// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
+template
+void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+// An overload for constant arrays.
+template
+void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+ float4 foobar[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ float4 baz[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ main0_out out = {};
+ out.FragColor = _46[in.index];
+ if (in.index < 10)
+ {
+ out.FragColor += _46[in.index ^ 1];
+ }
+ else
+ {
+ out.FragColor += _46[in.index & 1];
+ }
+ bool _99 = in.index > 30;
+ if (_99)
+ {
+ out.FragColor += _76[in.index & 3].y;
+ }
+ else
+ {
+ out.FragColor += _76[in.index & 1].x;
+ }
+ if (_99)
+ {
+ foobar[1].z = 20.0;
+ }
+ int _37 = in.index & 3;
+ out.FragColor += foobar[_37].z;
+ spvArrayCopyConstant(baz, _90);
+ out.FragColor += baz[_37].z;
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..e8a88623a2
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,22 @@
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ float3 vUV [[user(locn0)]];
+};
+
+fragment main0_out main0(main0_in in [[stage_in]], depth2d uShadow [[texture(0)]], depth2d uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
+{
+ main0_out out = {};
+ out.FragColor = uShadow.sample_compare(uShadowSmplr, in.vUV.xy, in.vUV.z) + uTexture.sample_compare(uSampler, in.vUV.xy, in.vUV.z);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..d453aadef0
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,17 @@
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+};
+
+vertex main0_out main0(uint gl_VertexIndex [[vertex_id]], uint gl_InstanceIndex [[instance_id]])
+{
+ main0_out out = {};
+ out.gl_Position = float4(float(gl_VertexIndex + gl_InstanceIndex));
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/array-lut-no-loop-variable.frag
index 6c8299fa91..60868acd87 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/array-lut-no-loop-variable.frag
@@ -1,5 +1,3 @@
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
#include
#include
@@ -12,28 +10,13 @@ struct main0_out
float4 FragColor [[color(0)]];
};
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template
-void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-// An overload for constant arrays.
-template
-void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
fragment main0_out main0()
{
main0_out out = {};
- float lut[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
for (int _46 = 0; _46 < 4; )
{
int _33 = _46 + 1;
- out.FragColor += float4(lut[_33]);
+ out.FragColor += float4(_17[_33]);
_46 = _33;
continue;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-array.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-array.frag
index 63576f109c..bb55934c6d 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-array.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-array.frag
@@ -44,10 +44,8 @@ void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
- float4 indexable[3] = {float4(1.0), float4(2.0), float4(3.0)};
- float4 indexable_1[2][2] = {{float4(1.0), float4(2.0)}, {float4(8.0), float4(10.0)}};
- Foobar indexable_2[2] = {{10.0, 40.0}, {90.0, 70.0}};
- out.FragColor = ((indexable[in.index] + (indexable_1[in.index][in.index + 1])) + float4(30.0)) + float4(indexable_2[in.index].a + indexable_2[in.index].b);
+ Foobar indexable[2] = {{10.0, 40.0}, {90.0, 70.0}};
+ out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + float4(30.0)) + float4(indexable[in.index].a + indexable[in.index].b);
return out;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-composites.frag
index ec5d66e86d..cb3e592337 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/constant-composites.frag
@@ -44,7 +44,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
float lut[4] = {1.0, 4.0, 3.0, 2.0};
Foo foos[2] = {{10.0, 20.0}, {30.0, 40.0}};
out.FragColor = float4(lut[in.line]);
- out.FragColor += float4(foos[in.line].a * (foos[1 - in.line].a));
+ out.FragColor += float4(foos[in.line].a * foos[1 - in.line].a);
return out;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..4efdf4a196
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/lut-promotion.frag
@@ -0,0 +1,69 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+constant float _16[16] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
+constant float4 _60[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+constant float4 _104[4] = {float4(20.0), float4(30.0), float4(50.0), float4(60.0)};
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ int index [[user(locn0)]];
+};
+
+// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
+template
+void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+// An overload for constant arrays.
+template
+void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+ main0_out out = {};
+ out.FragColor = _16[in.index];
+ if (in.index < 10)
+ {
+ out.FragColor += _16[in.index ^ 1];
+ }
+ else
+ {
+ out.FragColor += _16[in.index & 1];
+ }
+ bool _63 = in.index > 30;
+ if (_63)
+ {
+ out.FragColor += _60[in.index & 3].y;
+ }
+ else
+ {
+ out.FragColor += _60[in.index & 1].x;
+ }
+ float4 foobar[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ if (_63)
+ {
+ foobar[1].z = 20.0;
+ }
+ int _91 = in.index & 3;
+ out.FragColor += foobar[_91].z;
+ float4 baz[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ spvArrayCopyConstant(baz, _104);
+ out.FragColor += baz[_91].z;
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..5ab6b4fcb1
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/frag/spec-constant-ternary.frag
@@ -0,0 +1,22 @@
+#include
+#include
+
+using namespace metal;
+
+constant uint s_tmp [[function_constant(0)]];
+constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
+constant bool _13 = (s > 20u);
+constant uint _16 = _13 ? 30u : 50u;
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+fragment main0_out main0()
+{
+ main0_out out = {};
+ out.FragColor = float(_16);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/set_builtin_in_func.vert b/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/set_builtin_in_func.vert
new file mode 100644
index 0000000000..51a858af1e
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/set_builtin_in_func.vert
@@ -0,0 +1,19 @@
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+ float gl_PointSize [[point_size]];
+};
+
+vertex main0_out main0()
+{
+ main0_out out = {};
+ out.gl_PointSize = 1.0;
+ out.gl_Position = float4(out.gl_PointSize);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/texture_buffer.vert b/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/texture_buffer.vert
index f7bcb7918b..c45d298134 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/texture_buffer.vert
+++ b/deps/SPIRV-Cross/reference/opt/shaders-msl/vert/texture_buffer.vert
@@ -1,3 +1,5 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
#include
#include
@@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
+// Returns 2D texture coords corresponding to 1D texel buffer coords
+uint2 spvTexelBufferCoord(uint tc)
+{
+ return uint2(tc % 4096, tc / 4096);
+}
+
vertex main0_out main0(texture2d uSamp [[texture(4)]], texture2d uSampo [[texture(5)]])
{
main0_out out = {};
- out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
+ out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..d88c0e36d9
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,42 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+const float _46[16] = float[](1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
+const vec4 _76[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in mediump int index;
+
+void main()
+{
+ vec4 foobar[4] = _76;
+ vec4 baz[4] = _76;
+ FragColor = _46[index];
+ if (index < 10)
+ {
+ FragColor += _46[index ^ 1];
+ }
+ else
+ {
+ FragColor += _46[index & 1];
+ }
+ bool _99 = index > 30;
+ if (_99)
+ {
+ FragColor += _76[index & 3].y;
+ }
+ else
+ {
+ FragColor += _76[index & 1].x;
+ }
+ if (_99)
+ {
+ foobar[1].z = 20.0;
+ }
+ mediump int _37 = index & 3;
+ FragColor += foobar[_37].z;
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[_37].z;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/switch-label-shared-block.asm.frag b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/switch-label-shared-block.asm.frag
new file mode 100644
index 0000000000..ade9044e35
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/switch-label-shared-block.asm.frag
@@ -0,0 +1,33 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+layout(location = 0) flat in mediump int vIndex;
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ highp float _19;
+ switch (vIndex)
+ {
+ case 0:
+ case 2:
+ {
+ _19 = 1.0;
+ break;
+ }
+ case 1:
+ default:
+ {
+ _19 = 3.0;
+ break;
+ }
+ case 8:
+ {
+ _19 = 8.0;
+ break;
+ }
+ }
+ FragColor = _19;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag
new file mode 100644
index 0000000000..6953ec61d0
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag
@@ -0,0 +1,13 @@
+#version 450
+
+layout(binding = 0) uniform sampler2DShadow uShadow;
+uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
+
+layout(location = 0) in vec3 vUV;
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk
new file mode 100644
index 0000000000..2f997036f5
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk
@@ -0,0 +1,14 @@
+#version 450
+
+layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
+layout(set = 0, binding = 1) uniform texture2D uTexture;
+layout(set = 0, binding = 2) uniform samplerShadow uSampler;
+
+layout(location = 0) in vec3 vUV;
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/geom/store-uint-layer.invalid.asm.geom b/deps/SPIRV-Cross/reference/opt/shaders/asm/geom/store-uint-layer.invalid.asm.geom
new file mode 100644
index 0000000000..c768d5da86
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/geom/store-uint-layer.invalid.asm.geom
@@ -0,0 +1,41 @@
+#version 450
+layout(triangles) in;
+layout(max_vertices = 3, triangle_strip) out;
+
+struct VertexOutput
+{
+ vec4 pos;
+};
+
+struct GeometryOutput
+{
+ vec4 pos;
+ uint layer;
+};
+
+void _main(VertexOutput _input[3], GeometryOutput stream)
+{
+ GeometryOutput _output;
+ _output.layer = 1u;
+ for (int v = 0; v < 3; v++)
+ {
+ _output.pos = _input[v].pos;
+ gl_Position = _output.pos;
+ gl_Layer = int(_output.layer);
+ EmitVertex();
+ }
+ EndPrimitive();
+}
+
+void main()
+{
+ VertexOutput _input[3];
+ _input[0].pos = gl_in[0].gl_Position;
+ _input[1].pos = gl_in[1].gl_Position;
+ _input[2].pos = gl_in[2].gl_Position;
+ VertexOutput param[3] = _input;
+ GeometryOutput param_1;
+ _main(param, param_1);
+ GeometryOutput stream = param_1;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/opt/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..c25e9bbe5b
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,9 @@
+#version 450
+
+uniform int SPIRV_Cross_BaseInstance;
+
+void main()
+{
+ gl_Position = vec4(float(uint(gl_VertexID) + uint((gl_InstanceID + SPIRV_Cross_BaseInstance))));
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/comp/generate_height.comp b/deps/SPIRV-Cross/reference/opt/shaders/comp/generate_height.comp
index 17d3073d2e..ff96e7505a 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/comp/generate_height.comp
+++ b/deps/SPIRV-Cross/reference/opt/shaders/comp/generate_height.comp
@@ -48,8 +48,8 @@ void main()
vec2 _387 = _316.xx;
vec2 _392 = _316.yy;
vec2 _395 = _392 * _137.distribution[_280].yx;
- vec2 _421 = _392 * (_137.distribution[(_476 * _448) + _475]).yx;
- vec2 _429 = ((_137.distribution[(_476 * _448) + _475]) * _387) + vec2(-_421.x, _421.y);
+ vec2 _421 = _392 * _137.distribution[(_476 * _448) + _475].yx;
+ vec2 _429 = (_137.distribution[(_476 * _448) + _475] * _387) + vec2(-_421.x, _421.y);
_225.heights[_280] = packHalf2x16(((_137.distribution[_280] * _387) + vec2(-_395.x, _395.y)) + vec2(_429.x, -_429.y));
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/flatten/copy.flatten.vert b/deps/SPIRV-Cross/reference/opt/shaders/flatten/copy.flatten.vert
index 27ce450d62..33caec4f78 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/flatten/copy.flatten.vert
+++ b/deps/SPIRV-Cross/reference/opt/shaders/flatten/copy.flatten.vert
@@ -19,7 +19,7 @@ void main()
for (int _96 = 0; _96 < 4; )
{
vec3 _68 = aVertex.xyz - Light(UBO[_96 * 2 + 4].xyz, UBO[_96 * 2 + 4].w, UBO[_96 * 2 + 5]).Position;
- vColor += (((UBO[_96 * 2 + 5]) * clamp(1.0 - (length(_68) / Light(UBO[_96 * 2 + 4].xyz, UBO[_96 * 2 + 4].w, UBO[_96 * 2 + 5]).Radius), 0.0, 1.0)) * dot(aNormal, normalize(_68)));
+ vColor += ((UBO[_96 * 2 + 5] * clamp(1.0 - (length(_68) / Light(UBO[_96 * 2 + 4].xyz, UBO[_96 * 2 + 4].w, UBO[_96 * 2 + 5]).Radius), 0.0, 1.0)) * dot(aNormal, normalize(_68)));
_96++;
continue;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/flatten/dynamic.flatten.vert b/deps/SPIRV-Cross/reference/opt/shaders/flatten/dynamic.flatten.vert
index 8fc8ff6eed..7129af2869 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/flatten/dynamic.flatten.vert
+++ b/deps/SPIRV-Cross/reference/opt/shaders/flatten/dynamic.flatten.vert
@@ -18,8 +18,8 @@ void main()
vColor = vec4(0.0);
for (int _82 = 0; _82 < 4; )
{
- vec3 _54 = aVertex.xyz - (UBO[_82 * 2 + 4].xyz);
- vColor += (((UBO[_82 * 2 + 5]) * clamp(1.0 - (length(_54) / (UBO[_82 * 2 + 4].w)), 0.0, 1.0)) * dot(aNormal, normalize(_54)));
+ vec3 _54 = aVertex.xyz - UBO[_82 * 2 + 4].xyz;
+ vColor += ((UBO[_82 * 2 + 5] * clamp(1.0 - (length(_54) / UBO[_82 * 2 + 4].w), 0.0, 1.0)) * dot(aNormal, normalize(_54)));
_82++;
continue;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag b/deps/SPIRV-Cross/reference/opt/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
index 3657298f18..2ecee89377 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
@@ -25,6 +25,6 @@ void main()
}
}
}
- FragColor = ((values3[1 * 3 * 1 + 2 * 1 + 0]) + (values3[0 * 3 * 1 + 2 * 1 + 0])) + (values3[(vIndex + 1) * 3 * 1 + 2 * 1 + vIndex]);
+ FragColor = (values3[1 * 3 * 1 + 2 * 1 + 0] + values3[0 * 3 * 1 + 2 * 1 + 0]) + values3[(vIndex + 1) * 3 * 1 + 2 * 1 + vIndex];
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/opt/shaders/frag/array-lut-no-loop-variable.frag
index 7bdfe543e4..869a76e4e7 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders/frag/array-lut-no-loop-variable.frag
@@ -2,15 +2,16 @@
precision mediump float;
precision highp int;
+const float _17[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
+
layout(location = 0) out vec4 FragColor;
void main()
{
- float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
for (int _46 = 0; _46 < 4; )
{
mediump int _33 = _46 + 1;
- FragColor += vec4(lut[_33]);
+ FragColor += vec4(_17[_33]);
_46 = _33;
continue;
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-array.frag b/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-array.frag
index 2af87ad80d..749fc80980 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-array.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-array.frag
@@ -2,6 +2,9 @@
precision mediump float;
precision highp int;
+const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
+const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
+
struct Foobar
{
float a;
@@ -13,9 +16,7 @@ layout(location = 0) flat in mediump int index;
void main()
{
- highp vec4 indexable[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
- highp vec4 indexable_1[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
- Foobar indexable_2[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
- FragColor = ((indexable[index] + (indexable_1[index][index + 1])) + vec4(30.0)) + vec4(indexable_2[index].a + indexable_2[index].b);
+ Foobar indexable[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
+ FragColor = ((_37[index] + _55[index][index + 1]) + vec4(30.0)) + vec4(indexable[index].a + indexable[index].b);
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-composites.frag
index b105dbd26c..c65c60613d 100644
--- a/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/opt/shaders/frag/constant-composites.frag
@@ -18,6 +18,6 @@ void main()
lut = float[](1.0, 4.0, 3.0, 2.0);
foos = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
FragColor = vec4(lut[line]);
- FragColor += vec4(foos[line].a * (foos[1 - line].a));
+ FragColor += vec4(foos[line].a * foos[1 - line].a);
}
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/opt/shaders/frag/lut-promotion.frag
new file mode 100644
index 0000000000..21c925796e
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/frag/lut-promotion.frag
@@ -0,0 +1,42 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+const float _16[16] = float[](1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
+const vec4 _60[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in mediump int index;
+
+void main()
+{
+ FragColor = _16[index];
+ if (index < 10)
+ {
+ FragColor += _16[index ^ 1];
+ }
+ else
+ {
+ FragColor += _16[index & 1];
+ }
+ bool _63 = index > 30;
+ if (_63)
+ {
+ FragColor += _60[index & 3].y;
+ }
+ else
+ {
+ FragColor += _60[index & 1].x;
+ }
+ vec4 foobar[4] = _60;
+ if (_63)
+ {
+ foobar[1].z = 20.0;
+ }
+ mediump int _91 = index & 3;
+ FragColor += foobar[_91].z;
+ vec4 baz[4] = _60;
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[_91].z;
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag b/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag
new file mode 100644
index 0000000000..91b0331b79
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag
@@ -0,0 +1,9 @@
+#version 450
+
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = float((10u > 20u) ? 30u : 50u);
+}
+
diff --git a/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk b/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk
new file mode 100644
index 0000000000..59d3b99b9c
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/opt/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk
@@ -0,0 +1,13 @@
+#version 450
+
+layout(constant_id = 0) const uint s = 10u;
+const bool _13 = (s > 20u);
+const uint _16 = _13 ? 30u : 50u;
+
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = float(_16);
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/asm/comp/control-flow-hints.asm.comp b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
new file mode 100644
index 0000000000..9700100348
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
@@ -0,0 +1,41 @@
+RWByteAddressBuffer bar : register(u0);
+RWByteAddressBuffer foo : register(u1);
+
+void _main()
+{
+ [unroll]
+ for (int i = 0; i < 16; i++)
+ {
+ bar.Store4(i * 16 + 0, asuint(asfloat(foo.Load4(i * 16 + 0))));
+ }
+ [loop]
+ for (int i_1 = 0; i_1 < 16; i_1++)
+ {
+ bar.Store4((15 - i_1) * 16 + 0, asuint(asfloat(foo.Load4(i_1 * 16 + 0))));
+ }
+ float v = asfloat(bar.Load(160));
+ float w = asfloat(foo.Load(160));
+ [branch]
+ if (v > 10.0f)
+ {
+ foo.Store4(320, asuint(5.0f.xxxx));
+ }
+ float value = 20.0f;
+ [flatten]
+ if (w > 40.0f)
+ {
+ value = 20.0f;
+ }
+ foo.Store4(320, asuint(value.xxxx));
+}
+
+void comp_main()
+{
+ _main();
+}
+
+[numthreads(1, 1, 1)]
+void main()
+{
+ comp_main();
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..a7aec01bad
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,55 @@
+static const float _46[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
+static const float4 _76[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
+static const float4 _90[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
+
+static float FragColor;
+static int index;
+
+struct SPIRV_Cross_Input
+{
+ nointerpolation int index : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ float4 foobar[4] = _76;
+ float4 baz[4] = _76;
+ FragColor = _46[index];
+ if (index < 10)
+ {
+ FragColor += _46[index ^ 1];
+ }
+ else
+ {
+ FragColor += _46[index & 1];
+ }
+ if (index > 30)
+ {
+ FragColor += _76[index & 3].y;
+ }
+ else
+ {
+ FragColor += _76[index & 1].x;
+ }
+ if (index > 30)
+ {
+ foobar[1].z = 20.0f;
+ }
+ FragColor += foobar[index & 3].z;
+ baz = _90;
+ FragColor += baz[index & 3].z;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ index = stage_input.index;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..027dd00c5a
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,41 @@
+Texture2D uShadow : register(t0);
+SamplerComparisonState _uShadow_sampler : register(s0);
+Texture2D uTexture : register(t1);
+SamplerComparisonState uSampler : register(s2);
+
+static float3 vUV;
+static float FragColor;
+
+struct SPIRV_Cross_Input
+{
+ float3 vUV : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+float sample_combined()
+{
+ return uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z);
+}
+
+float sample_separate()
+{
+ return uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
+}
+
+void frag_main()
+{
+ FragColor = sample_combined() + sample_separate();
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ vUV = stage_input.vUV;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..a18c6e7056
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,37 @@
+static float4 gl_Position;
+static int gl_VertexIndex;
+static int gl_InstanceIndex;
+struct SPIRV_Cross_Input
+{
+ uint gl_VertexIndex : SV_VertexID;
+ uint gl_InstanceIndex : SV_InstanceID;
+};
+
+struct SPIRV_Cross_Output
+{
+ float4 gl_Position : SV_Position;
+};
+
+float4 _main(uint vid, uint iid)
+{
+ return float(vid + iid).xxxx;
+}
+
+void vert_main()
+{
+ uint vid = uint(gl_VertexIndex);
+ uint iid = uint(gl_InstanceIndex);
+ uint param = vid;
+ uint param_1 = iid;
+ gl_Position = _main(param, param_1);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ gl_VertexIndex = int(stage_input.gl_VertexIndex);
+ gl_InstanceIndex = int(stage_input.gl_InstanceIndex);
+ vert_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.gl_Position = gl_Position;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/comp/globallycoherent.comp b/deps/SPIRV-Cross/reference/shaders-hlsl/comp/globallycoherent.comp
new file mode 100644
index 0000000000..69886256f8
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/comp/globallycoherent.comp
@@ -0,0 +1,18 @@
+globallycoherent RWByteAddressBuffer _29 : register(u3);
+ByteAddressBuffer _33 : register(t2);
+RWTexture2D uImageIn : register(u0);
+globallycoherent RWTexture2D uImageOut : register(u1);
+
+void comp_main()
+{
+ int2 coord = int2(9, 7);
+ float4 indata = uImageIn[coord].xxxx;
+ uImageOut[coord] = indata.x;
+ _29.Store(0, asuint(asfloat(_33.Load(0))));
+}
+
+[numthreads(1, 1, 1)]
+void main()
+{
+ comp_main();
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/array-lut-no-loop-variable.frag
index 04d4d7fa75..407fa2bda4 100644
--- a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/array-lut-no-loop-variable.frag
@@ -15,8 +15,7 @@ struct SPIRV_Cross_Output
void frag_main()
{
- float lut[5] = _17;
- for (int i = 0; i < 4; i++, FragColor += lut[i].xxxx)
+ for (int i = 0; i < 4; i++, FragColor += _17[i].xxxx)
{
}
}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/constant-composites.frag
index 0514eef1ee..2613e1c2c5 100644
--- a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/constant-composites.frag
@@ -30,7 +30,7 @@ void frag_main()
lut = _16;
foos = _28;
FragColor = lut[_line].xxxx;
- FragColor += (foos[_line].a * (foos[1 - _line].a)).xxxx;
+ FragColor += (foos[_line].a * foos[1 - _line].a).xxxx;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..d148bc12cb
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/lut-promotion.frag
@@ -0,0 +1,55 @@
+static const float _16[16] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f };
+static const float4 _60[4] = { 0.0f.xxxx, 1.0f.xxxx, 8.0f.xxxx, 5.0f.xxxx };
+static const float4 _104[4] = { 20.0f.xxxx, 30.0f.xxxx, 50.0f.xxxx, 60.0f.xxxx };
+
+static float FragColor;
+static int index;
+
+struct SPIRV_Cross_Input
+{
+ nointerpolation int index : TEXCOORD0;
+};
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ FragColor = _16[index];
+ if (index < 10)
+ {
+ FragColor += _16[index ^ 1];
+ }
+ else
+ {
+ FragColor += _16[index & 1];
+ }
+ if (index > 30)
+ {
+ FragColor += _60[index & 3].y;
+ }
+ else
+ {
+ FragColor += _60[index & 1].x;
+ }
+ float4 foobar[4] = _60;
+ if (index > 30)
+ {
+ foobar[1].z = 20.0f;
+ }
+ FragColor += foobar[index & 3].z;
+ float4 baz[4] = _60;
+ baz = _104;
+ FragColor += baz[index & 3].z;
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+ index = stage_input.index;
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-hlsl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..12e0f5bd79
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-hlsl/frag/spec-constant-ternary.frag
@@ -0,0 +1,23 @@
+static const uint s = 10u;
+static const bool _13 = (s > 20u);
+static const uint _16 = _13 ? 30u : 50u;
+
+static float FragColor;
+
+struct SPIRV_Cross_Output
+{
+ float FragColor : SV_Target0;
+};
+
+void frag_main()
+{
+ FragColor = float(_16);
+}
+
+SPIRV_Cross_Output main()
+{
+ frag_main();
+ SPIRV_Cross_Output stage_output;
+ stage_output.FragColor = FragColor;
+ return stage_output;
+}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl-no-opt/vert/functions_nested.vert b/deps/SPIRV-Cross/reference/shaders-msl-no-opt/vert/functions_nested.vert
index 43a508613b..037ead3922 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl-no-opt/vert/functions_nested.vert
+++ b/deps/SPIRV-Cross/reference/shaders-msl-no-opt/vert/functions_nested.vert
@@ -36,6 +36,12 @@ struct main0_out
float4 gl_Position [[position]];
};
+// Returns 2D texture coords corresponding to 1D texel buffer coords
+uint2 spvTexelBufferCoord(uint tc)
+{
+ return uint2(tc % 4096, tc / 4096);
+}
+
attr_desc fetch_desc(thread const int& location, constant VertexBuffer& v_227)
{
int attribute_flags = v_227.input_attributes[location].w;
@@ -76,10 +82,10 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _131 = first_byte;
first_byte = _131 + 1;
- tmp.x = input_stream.read(uint2(_131, 0)).x;
+ tmp.x = input_stream.read(spvTexelBufferCoord(_131)).x;
int _138 = first_byte;
first_byte = _138 + 1;
- tmp.y = input_stream.read(uint2(_138, 0)).x;
+ tmp.y = input_stream.read(spvTexelBufferCoord(_138)).x;
uint4 param = tmp;
int param_1 = desc.swap_bytes;
result[n] = float(get_bits(param, param_1));
@@ -89,16 +95,16 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _156 = first_byte;
first_byte = _156 + 1;
- tmp.x = input_stream.read(uint2(_156, 0)).x;
+ tmp.x = input_stream.read(spvTexelBufferCoord(_156)).x;
int _163 = first_byte;
first_byte = _163 + 1;
- tmp.y = input_stream.read(uint2(_163, 0)).x;
+ tmp.y = input_stream.read(spvTexelBufferCoord(_163)).x;
int _170 = first_byte;
first_byte = _170 + 1;
- tmp.z = input_stream.read(uint2(_170, 0)).x;
+ tmp.z = input_stream.read(spvTexelBufferCoord(_170)).x;
int _177 = first_byte;
first_byte = _177 + 1;
- tmp.w = input_stream.read(uint2(_177, 0)).x;
+ tmp.w = input_stream.read(spvTexelBufferCoord(_177)).x;
uint4 param_2 = tmp;
int param_3 = desc.swap_bytes;
result[n] = as_type(get_bits(param_2, param_3));
@@ -108,7 +114,7 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _195 = first_byte;
first_byte = _195 + 1;
- result[n] = float(input_stream.read(uint2(_195, 0)).x);
+ result[n] = float(input_stream.read(spvTexelBufferCoord(_195)).x);
reverse_order = desc.swap_bytes != 0;
break;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..72d41f3e70
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,67 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+constant float _46[16] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
+constant float4 _76[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+constant float4 _90[4] = {float4(20.0), float4(30.0), float4(50.0), float4(60.0)};
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ int index [[user(locn0)]];
+};
+
+// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
+template
+void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+// An overload for constant arrays.
+template
+void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+ float4 foobar[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ float4 baz[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ main0_out out = {};
+ out.FragColor = _46[in.index];
+ if (in.index < 10)
+ {
+ out.FragColor += _46[in.index ^ 1];
+ }
+ else
+ {
+ out.FragColor += _46[in.index & 1];
+ }
+ if (in.index > 30)
+ {
+ out.FragColor += _76[in.index & 3].y;
+ }
+ else
+ {
+ out.FragColor += _76[in.index & 1].x;
+ }
+ if (in.index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ out.FragColor += foobar[in.index & 3].z;
+ spvArrayCopyConstant(baz, _90);
+ out.FragColor += baz[in.index & 3].z;
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/op-constant-null.asm.frag b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/op-constant-null.asm.frag
index 1d9d11c978..670cb5f371 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/op-constant-null.asm.frag
+++ b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/op-constant-null.asm.frag
@@ -1,5 +1,3 @@
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
#include
#include
@@ -18,20 +16,6 @@ struct main0_out
float FragColor [[color(0)]];
};
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template
-void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-// An overload for constant arrays.
-template
-void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
fragment main0_out main0()
{
main0_out out = {};
@@ -39,7 +23,6 @@ fragment main0_out main0()
float4 b = float4(0.0);
float2x3 c = float2x3(float3(0.0), float3(0.0));
D d = {float4(0.0), 0.0};
- float4 e[4] = {float4(0.0), float4(0.0), float4(0.0), float4(0.0)};
out.FragColor = a;
return out;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..005af22e3a
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,34 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ float3 vUV [[user(locn0)]];
+};
+
+float sample_combined(thread float3& vUV, thread depth2d uShadow, thread const sampler uShadowSmplr)
+{
+ return uShadow.sample_compare(uShadowSmplr, vUV.xy, vUV.z);
+}
+
+float sample_separate(thread float3& vUV, thread depth2d uTexture, thread sampler uSampler)
+{
+ return uTexture.sample_compare(uSampler, vUV.xy, vUV.z);
+}
+
+fragment main0_out main0(main0_in in [[stage_in]], depth2d uShadow [[texture(0)]], depth2d uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
+{
+ main0_out out = {};
+ out.FragColor = sample_combined(in.vUV, uShadow, uShadowSmplr) + sample_separate(in.vUV, uTexture, uSampler);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..89ca17f98b
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,28 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+};
+
+float4 _main(thread const uint& vid, thread const uint& iid)
+{
+ return float4(float(vid + iid));
+}
+
+vertex main0_out main0(uint gl_VertexIndex [[vertex_id]], uint gl_InstanceIndex [[instance_id]])
+{
+ main0_out out = {};
+ uint vid = gl_VertexIndex;
+ uint iid = gl_InstanceIndex;
+ uint param = vid;
+ uint param_1 = iid;
+ out.gl_Position = _main(param, param_1);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/comp/composite-construct.comp b/deps/SPIRV-Cross/reference/shaders-msl/comp/composite-construct.comp
index fb4ed1f101..ef0412b1dc 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/comp/composite-construct.comp
+++ b/deps/SPIRV-Cross/reference/shaders-msl/comp/composite-construct.comp
@@ -42,8 +42,7 @@ kernel void main0(device SSBO0& _16 [[buffer(0)]], device SSBO1& _32 [[buffer(1)
float4 _37[2] = { _16.as[gl_GlobalInvocationID.x], _32.bs[gl_GlobalInvocationID.x] };
float4 values[2];
spvArrayCopy(values, _37);
- float4 copy_values[2] = {float4(20.0), float4(40.0)};
- Composite c = Composite{ values[0], copy_values[1] };
+ Composite c = Composite{ values[0], _43[1] };
_16.as[0] = values[gl_LocalInvocationIndex];
_32.bs[1] = c.b;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/shaders-msl/frag/array-lut-no-loop-variable.frag
index 8943a8e5a1..37f83aae26 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/shaders-msl/frag/array-lut-no-loop-variable.frag
@@ -1,5 +1,3 @@
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
#include
#include
@@ -12,25 +10,10 @@ struct main0_out
float4 FragColor [[color(0)]];
};
-// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
-template
-void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
-// An overload for constant arrays.
-template
-void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
-{
- for (uint i = 0; i < N; dst[i] = src[i], i++);
-}
-
fragment main0_out main0()
{
main0_out out = {};
- float lut[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
- for (int i = 0; i < 4; i++, out.FragColor += float4(lut[i]))
+ for (int i = 0; i < 4; i++, out.FragColor += float4(_17[i]))
{
}
return out;
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-array.frag b/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-array.frag
index 09f123b29a..212d4f0803 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-array.frag
+++ b/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-array.frag
@@ -49,12 +49,10 @@ float4 resolve(thread const Foobar& f)
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
- float4 indexable[3] = {float4(1.0), float4(2.0), float4(3.0)};
- float4 indexable_1[2][2] = {{float4(1.0), float4(2.0)}, {float4(8.0), float4(10.0)}};
Foobar param = {10.0, 20.0};
- Foobar indexable_2[2] = {{10.0, 40.0}, {90.0, 70.0}};
- Foobar param_1 = indexable_2[in.index];
- out.FragColor = ((indexable[in.index] + (indexable_1[in.index][in.index + 1])) + resolve(param)) + resolve(param_1);
+ Foobar indexable[2] = {{10.0, 40.0}, {90.0, 70.0}};
+ Foobar param_1 = indexable[in.index];
+ out.FragColor = ((_37[in.index] + _55[in.index][in.index + 1]) + resolve(param)) + resolve(param_1);
return out;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-composites.frag
index ec5d66e86d..cb3e592337 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/shaders-msl/frag/constant-composites.frag
@@ -44,7 +44,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
float lut[4] = {1.0, 4.0, 3.0, 2.0};
Foo foos[2] = {{10.0, 20.0}, {30.0, 40.0}};
out.FragColor = float4(lut[in.line]);
- out.FragColor += float4(foos[in.line].a * (foos[1 - in.line].a));
+ out.FragColor += float4(foos[in.line].a * foos[1 - in.line].a);
return out;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/shaders-msl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..a8eda3e13a
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/frag/lut-promotion.frag
@@ -0,0 +1,67 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+constant float _16[16] = {1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0};
+constant float4 _60[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+constant float4 _104[4] = {float4(20.0), float4(30.0), float4(50.0), float4(60.0)};
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+struct main0_in
+{
+ int index [[user(locn0)]];
+};
+
+// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
+template
+void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+// An overload for constant arrays.
+template
+void spvArrayCopyConstant(thread T (&dst)[N], constant T (&src)[N])
+{
+ for (uint i = 0; i < N; dst[i] = src[i], i++);
+}
+
+fragment main0_out main0(main0_in in [[stage_in]])
+{
+ main0_out out = {};
+ out.FragColor = _16[in.index];
+ if (in.index < 10)
+ {
+ out.FragColor += _16[in.index ^ 1];
+ }
+ else
+ {
+ out.FragColor += _16[in.index & 1];
+ }
+ if (in.index > 30)
+ {
+ out.FragColor += _60[in.index & 3].y;
+ }
+ else
+ {
+ out.FragColor += _60[in.index & 1].x;
+ }
+ float4 foobar[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ if (in.index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ out.FragColor += foobar[in.index & 3].z;
+ float4 baz[4] = {float4(0.0), float4(1.0), float4(8.0), float4(5.0)};
+ spvArrayCopyConstant(baz, _104);
+ out.FragColor += baz[in.index & 3].z;
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/reference/shaders-msl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..5ab6b4fcb1
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/frag/spec-constant-ternary.frag
@@ -0,0 +1,22 @@
+#include
+#include
+
+using namespace metal;
+
+constant uint s_tmp [[function_constant(0)]];
+constant uint s = is_function_constant_defined(s_tmp) ? s_tmp : 10u;
+constant bool _13 = (s > 20u);
+constant uint _16 = _13 ? 30u : 50u;
+
+struct main0_out
+{
+ float FragColor [[color(0)]];
+};
+
+fragment main0_out main0()
+{
+ main0_out out = {};
+ out.FragColor = float(_16);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/vert/set_builtin_in_func.vert b/deps/SPIRV-Cross/reference/shaders-msl/vert/set_builtin_in_func.vert
new file mode 100644
index 0000000000..2952748dc0
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-msl/vert/set_builtin_in_func.vert
@@ -0,0 +1,26 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include
+#include
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+ float gl_PointSize [[point_size]];
+};
+
+void write_outblock(thread float4& gl_Position, thread float& gl_PointSize)
+{
+ gl_PointSize = 1.0;
+ gl_Position = float4(gl_PointSize);
+}
+
+vertex main0_out main0()
+{
+ main0_out out = {};
+ write_outblock(out.gl_Position, out.gl_PointSize);
+ return out;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders-msl/vert/texture_buffer.vert b/deps/SPIRV-Cross/reference/shaders-msl/vert/texture_buffer.vert
index f7bcb7918b..c45d298134 100644
--- a/deps/SPIRV-Cross/reference/shaders-msl/vert/texture_buffer.vert
+++ b/deps/SPIRV-Cross/reference/shaders-msl/vert/texture_buffer.vert
@@ -1,3 +1,5 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
#include
#include
@@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
+// Returns 2D texture coords corresponding to 1D texel buffer coords
+uint2 spvTexelBufferCoord(uint tc)
+{
+ return uint2(tc % 4096, tc / 4096);
+}
+
vertex main0_out main0(texture2d uSamp [[texture(4)]], texture2d uSampo [[texture(5)]])
{
main0_out out = {};
- out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
+ out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/asm/aliased-entry-point-names.asm.multi.json b/deps/SPIRV-Cross/reference/shaders-reflection/asm/aliased-entry-point-names.asm.multi.json
new file mode 100644
index 0000000000..45adf50b14
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/asm/aliased-entry-point-names.asm.multi.json
@@ -0,0 +1,49 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "vert"
+ },
+ {
+ "name" : "main2",
+ "mode" : "vert"
+ },
+ {
+ "name" : "main",
+ "mode" : "frag"
+ },
+ {
+ "name" : "main2",
+ "mode" : "frag"
+ }
+ ],
+ "types" : {
+ "_8" : {
+ "name" : "_8",
+ "members" : [
+ {
+ "name" : "_m0",
+ "type" : "vec4"
+ },
+ {
+ "name" : "_m1",
+ "type" : "float"
+ },
+ {
+ "name" : "_m2",
+ "type" : "float",
+ "array" : [
+ 1
+ ]
+ },
+ {
+ "name" : "_m3",
+ "type" : "float",
+ "array" : [
+ 1
+ ]
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-layout.comp.json b/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-layout.comp.json
new file mode 100644
index 0000000000..3004454b80
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-layout.comp.json
@@ -0,0 +1,64 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "comp"
+ }
+ ],
+ "types" : {
+ "_19" : {
+ "name" : "Foo",
+ "members" : [
+ {
+ "name" : "m",
+ "type" : "mat4",
+ "offset" : 0
+ }
+ ]
+ },
+ "_21" : {
+ "name" : "SSBO2",
+ "members" : [
+ {
+ "name" : "out_data",
+ "type" : "_19",
+ "array" : [
+ 0
+ ],
+ "offset" : 0
+ }
+ ]
+ },
+ "_28" : {
+ "name" : "SSBO",
+ "members" : [
+ {
+ "name" : "in_data",
+ "type" : "_19",
+ "array" : [
+ 0
+ ],
+ "offset" : 0
+ }
+ ]
+ }
+ },
+ "ssbos" : [
+ {
+ "type" : "_21",
+ "name" : "SSBO2",
+ "writeonly" : true,
+ "block_size" : 0,
+ "set" : 0,
+ "binding" : 1
+ },
+ {
+ "type" : "_28",
+ "name" : "SSBO",
+ "readonly" : true,
+ "block_size" : 0,
+ "set" : 0,
+ "binding" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-packing.comp.json b/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-packing.comp.json
new file mode 100644
index 0000000000..22a41584d9
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/comp/struct-packing.comp.json
@@ -0,0 +1,474 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "comp"
+ }
+ ],
+ "types" : {
+ "_11" : {
+ "name" : "S0",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec2",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 8
+ }
+ ]
+ },
+ "_14" : {
+ "name" : "S1",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec3",
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 12
+ }
+ ]
+ },
+ "_17" : {
+ "name" : "S2",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec3",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 16
+ }
+ ]
+ },
+ "_19" : {
+ "name" : "S3",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec2",
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 8
+ }
+ ]
+ },
+ "_20" : {
+ "name" : "S4",
+ "members" : [
+ {
+ "name" : "c",
+ "type" : "vec2",
+ "offset" : 0
+ }
+ ]
+ },
+ "_23" : {
+ "name" : "Content",
+ "members" : [
+ {
+ "name" : "m0s",
+ "type" : "_11",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "m1s",
+ "type" : "_14",
+ "array" : [
+ 1
+ ],
+ "offset" : 16
+ },
+ {
+ "name" : "m2s",
+ "type" : "_17",
+ "array" : [
+ 1
+ ],
+ "offset" : 32
+ },
+ {
+ "name" : "m0",
+ "type" : "_11",
+ "offset" : 64
+ },
+ {
+ "name" : "m1",
+ "type" : "_14",
+ "offset" : 80
+ },
+ {
+ "name" : "m2",
+ "type" : "_17",
+ "offset" : 96
+ },
+ {
+ "name" : "m3",
+ "type" : "_19",
+ "offset" : 128
+ },
+ {
+ "name" : "m4",
+ "type" : "float",
+ "offset" : 144
+ },
+ {
+ "name" : "m3s",
+ "type" : "_20",
+ "array" : [
+ 8
+ ],
+ "offset" : 152
+ }
+ ]
+ },
+ "_36" : {
+ "name" : "SSBO1",
+ "members" : [
+ {
+ "name" : "content",
+ "type" : "_23",
+ "offset" : 0
+ },
+ {
+ "name" : "content1",
+ "type" : "_23",
+ "array" : [
+ 2
+ ],
+ "offset" : 224
+ },
+ {
+ "name" : "content2",
+ "type" : "_23",
+ "offset" : 672
+ },
+ {
+ "name" : "m0",
+ "type" : "mat2",
+ "offset" : 896
+ },
+ {
+ "name" : "m1",
+ "type" : "mat2",
+ "offset" : 912
+ },
+ {
+ "name" : "m2",
+ "type" : "mat2x3",
+ "array" : [
+ 4
+ ],
+ "offset" : 928
+ },
+ {
+ "name" : "m3",
+ "type" : "mat3x2",
+ "offset" : 1056
+ },
+ {
+ "name" : "m4",
+ "type" : "mat2",
+ "row_major" : true,
+ "offset" : 1080
+ },
+ {
+ "name" : "m5",
+ "type" : "mat2",
+ "row_major" : true,
+ "array" : [
+ 9
+ ],
+ "offset" : 1096
+ },
+ {
+ "name" : "m6",
+ "type" : "mat2x3",
+ "row_major" : true,
+ "array" : [
+ 2,
+ 4
+ ],
+ "offset" : 1240
+ },
+ {
+ "name" : "m7",
+ "type" : "mat3x2",
+ "row_major" : true,
+ "offset" : 1440
+ },
+ {
+ "name" : "array",
+ "type" : "float",
+ "array" : [
+ 0
+ ],
+ "offset" : 1472
+ }
+ ]
+ },
+ "_42" : {
+ "name" : "S0",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec2",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 16
+ }
+ ]
+ },
+ "_44" : {
+ "name" : "S1",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec3",
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 12
+ }
+ ]
+ },
+ "_47" : {
+ "name" : "S2",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec3",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 16
+ }
+ ]
+ },
+ "_49" : {
+ "name" : "S3",
+ "members" : [
+ {
+ "name" : "a",
+ "type" : "vec2",
+ "offset" : 0
+ },
+ {
+ "name" : "b",
+ "type" : "float",
+ "offset" : 8
+ }
+ ]
+ },
+ "_50" : {
+ "name" : "S4",
+ "members" : [
+ {
+ "name" : "c",
+ "type" : "vec2",
+ "offset" : 0
+ }
+ ]
+ },
+ "_52" : {
+ "name" : "Content",
+ "members" : [
+ {
+ "name" : "m0s",
+ "type" : "_42",
+ "array" : [
+ 1
+ ],
+ "offset" : 0
+ },
+ {
+ "name" : "m1s",
+ "type" : "_44",
+ "array" : [
+ 1
+ ],
+ "offset" : 32
+ },
+ {
+ "name" : "m2s",
+ "type" : "_47",
+ "array" : [
+ 1
+ ],
+ "offset" : 48
+ },
+ {
+ "name" : "m0",
+ "type" : "_42",
+ "offset" : 80
+ },
+ {
+ "name" : "m1",
+ "type" : "_44",
+ "offset" : 112
+ },
+ {
+ "name" : "m2",
+ "type" : "_47",
+ "offset" : 128
+ },
+ {
+ "name" : "m3",
+ "type" : "_49",
+ "offset" : 160
+ },
+ {
+ "name" : "m4",
+ "type" : "float",
+ "offset" : 176
+ },
+ {
+ "name" : "m3s",
+ "type" : "_50",
+ "array" : [
+ 8
+ ],
+ "offset" : 192
+ }
+ ]
+ },
+ "_59" : {
+ "name" : "SSBO0",
+ "members" : [
+ {
+ "name" : "content",
+ "type" : "_52",
+ "offset" : 0
+ },
+ {
+ "name" : "content1",
+ "type" : "_52",
+ "array" : [
+ 2
+ ],
+ "offset" : 320
+ },
+ {
+ "name" : "content2",
+ "type" : "_52",
+ "offset" : 960
+ },
+ {
+ "name" : "m0",
+ "type" : "mat2",
+ "offset" : 1280
+ },
+ {
+ "name" : "m1",
+ "type" : "mat2",
+ "offset" : 1312
+ },
+ {
+ "name" : "m2",
+ "type" : "mat2x3",
+ "array" : [
+ 4
+ ],
+ "offset" : 1344
+ },
+ {
+ "name" : "m3",
+ "type" : "mat3x2",
+ "offset" : 1472
+ },
+ {
+ "name" : "m4",
+ "type" : "mat2",
+ "row_major" : true,
+ "offset" : 1520
+ },
+ {
+ "name" : "m5",
+ "type" : "mat2",
+ "row_major" : true,
+ "array" : [
+ 9
+ ],
+ "offset" : 1552
+ },
+ {
+ "name" : "m6",
+ "type" : "mat2x3",
+ "row_major" : true,
+ "array" : [
+ 2,
+ 4
+ ],
+ "offset" : 1840
+ },
+ {
+ "name" : "m7",
+ "type" : "mat3x2",
+ "row_major" : true,
+ "offset" : 2224
+ },
+ {
+ "name" : "array",
+ "type" : "float",
+ "array" : [
+ 0
+ ],
+ "offset" : 2256
+ }
+ ]
+ }
+ },
+ "ssbos" : [
+ {
+ "type" : "_36",
+ "name" : "SSBO1",
+ "restrict" : true,
+ "block_size" : 1472,
+ "set" : 0,
+ "binding" : 1
+ },
+ {
+ "type" : "_59",
+ "name" : "SSBO0",
+ "restrict" : true,
+ "block_size" : 2256,
+ "set" : 0,
+ "binding" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag.json
new file mode 100644
index 0000000000..5b4d3c6f7b
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag.json
@@ -0,0 +1,37 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "float",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ],
+ "separate_images" : [
+ {
+ "type" : "texture2D",
+ "name" : "uDepth",
+ "set" : 0,
+ "binding" : 2
+ }
+ ],
+ "separate_samplers" : [
+ {
+ "type" : "sampler",
+ "name" : "uSampler",
+ "set" : 0,
+ "binding" : 0
+ },
+ {
+ "type" : "sampler",
+ "name" : "uSampler1",
+ "set" : 0,
+ "binding" : 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler.vk.frag.json
new file mode 100644
index 0000000000..8b6a184299
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/combined-texture-sampler.vk.frag.json
@@ -0,0 +1,50 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "inputs" : [
+ {
+ "type" : "vec2",
+ "name" : "vTex",
+ "location" : 0
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ],
+ "separate_images" : [
+ {
+ "type" : "texture2D",
+ "name" : "uTexture0",
+ "set" : 0,
+ "binding" : 2
+ },
+ {
+ "type" : "texture2D",
+ "name" : "uTexture1",
+ "set" : 0,
+ "binding" : 3
+ }
+ ],
+ "separate_samplers" : [
+ {
+ "type" : "sampler",
+ "name" : "uSampler0",
+ "set" : 0,
+ "binding" : 0
+ },
+ {
+ "type" : "sampler",
+ "name" : "uSampler1",
+ "set" : 0,
+ "binding" : 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/image-load-store-uint-coord.asm.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/image-load-store-uint-coord.asm.frag.json
new file mode 100644
index 0000000000..527ea2bfee
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/image-load-store-uint-coord.asm.frag.json
@@ -0,0 +1,47 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "_entryPointOutput",
+ "location" : 0
+ }
+ ],
+ "textures" : [
+ {
+ "type" : "sampler2D",
+ "name" : "ROIm",
+ "set" : 0,
+ "binding" : 1
+ }
+ ],
+ "separate_images" : [
+ {
+ "type" : "samplerBuffer",
+ "name" : "ROBuf",
+ "set" : 0,
+ "binding" : 0
+ }
+ ],
+ "images" : [
+ {
+ "type" : "image2D",
+ "name" : "RWIm",
+ "set" : 0,
+ "binding" : 1,
+ "format" : "rgba32f"
+ },
+ {
+ "type" : "imageBuffer",
+ "name" : "RWBuf",
+ "set" : 0,
+ "binding" : 0,
+ "format" : "rgba32f"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment-ms.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment-ms.vk.frag.json
new file mode 100644
index 0000000000..5f381911ac
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment-ms.vk.frag.json
@@ -0,0 +1,31 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "subpass_inputs" : [
+ {
+ "type" : "subpassInputMS",
+ "name" : "uSubpass0",
+ "set" : 0,
+ "binding" : 0,
+ "input_attachment_index" : 0
+ },
+ {
+ "type" : "subpassInputMS",
+ "name" : "uSubpass1",
+ "set" : 0,
+ "binding" : 1,
+ "input_attachment_index" : 1
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment.vk.frag.json
new file mode 100644
index 0000000000..16ae6a4683
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/input-attachment.vk.frag.json
@@ -0,0 +1,31 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "subpass_inputs" : [
+ {
+ "type" : "subpassInput",
+ "name" : "uSubpass0",
+ "set" : 0,
+ "binding" : 0,
+ "input_attachment_index" : 0
+ },
+ {
+ "type" : "subpassInput",
+ "name" : "uSubpass1",
+ "set" : 0,
+ "binding" : 1,
+ "input_attachment_index" : 1
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/push-constant.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/push-constant.vk.frag.json
new file mode 100644
index 0000000000..f72a8fd654
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/push-constant.vk.frag.json
@@ -0,0 +1,46 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "types" : {
+ "_13" : {
+ "name" : "PushConstants",
+ "members" : [
+ {
+ "name" : "value0",
+ "type" : "vec4",
+ "offset" : 0
+ },
+ {
+ "name" : "value1",
+ "type" : "vec4",
+ "offset" : 16
+ }
+ ]
+ }
+ },
+ "inputs" : [
+ {
+ "type" : "vec4",
+ "name" : "vColor",
+ "location" : 0
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ],
+ "push_constants" : [
+ {
+ "type" : "_13",
+ "name" : "push",
+ "push_constant" : true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/separate-sampler-texture-array.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/separate-sampler-texture-array.vk.frag.json
new file mode 100644
index 0000000000..9216d93e5d
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/separate-sampler-texture-array.vk.frag.json
@@ -0,0 +1,73 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "inputs" : [
+ {
+ "type" : "vec2",
+ "name" : "vTex",
+ "location" : 0
+ },
+ {
+ "type" : "vec3",
+ "name" : "vTex3",
+ "location" : 1
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ],
+ "separate_images" : [
+ {
+ "type" : "texture2D",
+ "name" : "uTexture",
+ "array" : [
+ 4
+ ],
+ "set" : 0,
+ "binding" : 1
+ },
+ {
+ "type" : "texture2DArray",
+ "name" : "uTextureArray",
+ "array" : [
+ 4
+ ],
+ "set" : 0,
+ "binding" : 4
+ },
+ {
+ "type" : "textureCube",
+ "name" : "uTextureCube",
+ "array" : [
+ 4
+ ],
+ "set" : 0,
+ "binding" : 3
+ },
+ {
+ "type" : "texture3D",
+ "name" : "uTexture3D",
+ "array" : [
+ 4
+ ],
+ "set" : 0,
+ "binding" : 2
+ }
+ ],
+ "separate_samplers" : [
+ {
+ "type" : "sampler",
+ "name" : "uSampler",
+ "set" : 0,
+ "binding" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/frag/spec-constant.vk.frag.json b/deps/SPIRV-Cross/reference/shaders-reflection/frag/spec-constant.vk.frag.json
new file mode 100644
index 0000000000..0add298666
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/frag/spec-constant.vk.frag.json
@@ -0,0 +1,71 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "frag"
+ }
+ ],
+ "types" : {
+ "_137" : {
+ "name" : "Foo",
+ "members" : [
+ {
+ "name" : "elems",
+ "type" : "float",
+ "array" : [
+ 135
+ ]
+ }
+ ]
+ }
+ },
+ "outputs" : [
+ {
+ "type" : "vec4",
+ "name" : "FragColor",
+ "location" : 0
+ }
+ ],
+ "specialization_constants" : [
+ {
+ "id" : 1,
+ "type" : "float",
+ "default_value" : 1.5
+ },
+ {
+ "id" : 2,
+ "type" : "float",
+ "default_value" : 2.5
+ },
+ {
+ "id" : 3,
+ "type" : "int",
+ "default_value" : 3
+ },
+ {
+ "id" : 4,
+ "type" : "int",
+ "default_value" : 4
+ },
+ {
+ "id" : 5,
+ "type" : "uint",
+ "default_value" : 5
+ },
+ {
+ "id" : 6,
+ "type" : "uint",
+ "default_value" : 6
+ },
+ {
+ "id" : 7,
+ "type" : "bool",
+ "default_value" : false
+ },
+ {
+ "id" : 8,
+ "type" : "bool",
+ "default_value" : true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/vert/read-from-row-major-array.vert.json b/deps/SPIRV-Cross/reference/shaders-reflection/vert/read-from-row-major-array.vert.json
new file mode 100644
index 0000000000..d92fb67fb5
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/vert/read-from-row-major-array.vert.json
@@ -0,0 +1,61 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "vert"
+ }
+ ],
+ "types" : {
+ "_89" : {
+ "name" : "gl_PerVertex",
+ "members" : [
+ {
+ "name" : "gl_Position",
+ "type" : "vec4"
+ },
+ {
+ "name" : "gl_PointSize",
+ "type" : "float"
+ }
+ ]
+ },
+ "_102" : {
+ "name" : "Block",
+ "members" : [
+ {
+ "name" : "var",
+ "type" : "mat2x3",
+ "row_major" : true,
+ "array" : [
+ 4,
+ 3
+ ],
+ "offset" : 0
+ }
+ ]
+ }
+ },
+ "inputs" : [
+ {
+ "type" : "vec4",
+ "name" : "a_position",
+ "location" : 0
+ }
+ ],
+ "outputs" : [
+ {
+ "type" : "float",
+ "name" : "v_vtxResult",
+ "location" : 0
+ }
+ ],
+ "ubos" : [
+ {
+ "type" : "_102",
+ "name" : "Block",
+ "block_size" : 576,
+ "set" : 0,
+ "binding" : 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders-reflection/vert/texture_buffer.vert.json b/deps/SPIRV-Cross/reference/shaders-reflection/vert/texture_buffer.vert.json
new file mode 100644
index 0000000000..3c69e24cbc
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders-reflection/vert/texture_buffer.vert.json
@@ -0,0 +1,40 @@
+{
+ "entryPoints" : [
+ {
+ "name" : "main",
+ "mode" : "vert"
+ }
+ ],
+ "types" : {
+ "_8" : {
+ "name" : "gl_PerVertex",
+ "members" : [
+ {
+ "name" : "gl_Position",
+ "type" : "vec4"
+ },
+ {
+ "name" : "gl_PointSize",
+ "type" : "float"
+ }
+ ]
+ }
+ },
+ "textures" : [
+ {
+ "type" : "samplerBuffer",
+ "name" : "uSamp",
+ "set" : 0,
+ "binding" : 4
+ }
+ ],
+ "images" : [
+ {
+ "type" : "imageBuffer",
+ "name" : "uSampo",
+ "set" : 0,
+ "binding" : 5,
+ "format" : "rgba32f"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/reference/shaders/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..c08bc2c781
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,40 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+const float _46[16] = float[](1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
+const vec4 _76[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in mediump int index;
+
+void main()
+{
+ vec4 foobar[4] = _76;
+ vec4 baz[4] = _76;
+ FragColor = _46[index];
+ if (index < 10)
+ {
+ FragColor += _46[index ^ 1];
+ }
+ else
+ {
+ FragColor += _46[index & 1];
+ }
+ if (index > 30)
+ {
+ FragColor += _76[index & 3].y;
+ }
+ else
+ {
+ FragColor += _76[index & 1].x;
+ }
+ if (index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ FragColor += foobar[index & 3].z;
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[index & 3].z;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/frag/op-constant-null.asm.frag b/deps/SPIRV-Cross/reference/shaders/asm/frag/op-constant-null.asm.frag
index c4ae981f64..970b4c4a66 100644
--- a/deps/SPIRV-Cross/reference/shaders/asm/frag/op-constant-null.asm.frag
+++ b/deps/SPIRV-Cross/reference/shaders/asm/frag/op-constant-null.asm.frag
@@ -2,6 +2,8 @@
precision mediump float;
precision highp int;
+const vec4 _14[4] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
+
struct D
{
vec4 a;
@@ -16,7 +18,6 @@ void main()
vec4 b = vec4(0.0);
mat2x3 c = mat2x3(vec3(0.0), vec3(0.0));
D d = D(vec4(0.0), 0.0);
- vec4 e[4] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
FragColor = a;
}
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/frag/switch-label-shared-block.asm.frag b/deps/SPIRV-Cross/reference/shaders/asm/frag/switch-label-shared-block.asm.frag
new file mode 100644
index 0000000000..ade9044e35
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/frag/switch-label-shared-block.asm.frag
@@ -0,0 +1,33 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+layout(location = 0) flat in mediump int vIndex;
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ highp float _19;
+ switch (vIndex)
+ {
+ case 0:
+ case 2:
+ {
+ _19 = 1.0;
+ break;
+ }
+ case 1:
+ default:
+ {
+ _19 = 3.0;
+ break;
+ }
+ case 8:
+ {
+ _19 = 8.0;
+ break;
+ }
+ }
+ FragColor = _19;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag b/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag
new file mode 100644
index 0000000000..7729d30c09
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag
@@ -0,0 +1,23 @@
+#version 450
+
+layout(binding = 0) uniform sampler2DShadow uShadow;
+uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
+
+layout(location = 0) in vec3 vUV;
+layout(location = 0) out float FragColor;
+
+float sample_combined()
+{
+ return texture(uShadow, vec3(vUV.xy, vUV.z));
+}
+
+float sample_separate()
+{
+ return texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
+}
+
+void main()
+{
+ FragColor = sample_combined() + sample_separate();
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk b/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk
new file mode 100644
index 0000000000..711fa27763
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag.vk
@@ -0,0 +1,24 @@
+#version 450
+
+layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
+layout(set = 0, binding = 1) uniform texture2D uTexture;
+layout(set = 0, binding = 2) uniform samplerShadow uSampler;
+
+layout(location = 0) in vec3 vUV;
+layout(location = 0) out float FragColor;
+
+float sample_combined()
+{
+ return texture(uShadow, vec3(vUV.xy, vUV.z));
+}
+
+float sample_separate()
+{
+ return texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
+}
+
+void main()
+{
+ FragColor = sample_combined() + sample_separate();
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/geom/store-uint-layer.invalid.asm.geom b/deps/SPIRV-Cross/reference/shaders/asm/geom/store-uint-layer.invalid.asm.geom
new file mode 100644
index 0000000000..c768d5da86
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/geom/store-uint-layer.invalid.asm.geom
@@ -0,0 +1,41 @@
+#version 450
+layout(triangles) in;
+layout(max_vertices = 3, triangle_strip) out;
+
+struct VertexOutput
+{
+ vec4 pos;
+};
+
+struct GeometryOutput
+{
+ vec4 pos;
+ uint layer;
+};
+
+void _main(VertexOutput _input[3], GeometryOutput stream)
+{
+ GeometryOutput _output;
+ _output.layer = 1u;
+ for (int v = 0; v < 3; v++)
+ {
+ _output.pos = _input[v].pos;
+ gl_Position = _output.pos;
+ gl_Layer = int(_output.layer);
+ EmitVertex();
+ }
+ EndPrimitive();
+}
+
+void main()
+{
+ VertexOutput _input[3];
+ _input[0].pos = gl_in[0].gl_Position;
+ _input[1].pos = gl_in[1].gl_Position;
+ _input[2].pos = gl_in[2].gl_Position;
+ VertexOutput param[3] = _input;
+ GeometryOutput param_1;
+ _main(param, param_1);
+ GeometryOutput stream = param_1;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/reference/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..31f13bd777
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,18 @@
+#version 450
+
+uniform int SPIRV_Cross_BaseInstance;
+
+vec4 _main(uint vid, uint iid)
+{
+ return vec4(float(vid + iid));
+}
+
+void main()
+{
+ uint vid = uint(gl_VertexID);
+ uint iid = uint((gl_InstanceID + SPIRV_Cross_BaseInstance));
+ uint param = vid;
+ uint param_1 = iid;
+ gl_Position = _main(param, param_1);
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/comp/composite-construct.comp b/deps/SPIRV-Cross/reference/shaders/comp/composite-construct.comp
index 91bb5348f5..3018be8f1b 100644
--- a/deps/SPIRV-Cross/reference/shaders/comp/composite-construct.comp
+++ b/deps/SPIRV-Cross/reference/shaders/comp/composite-construct.comp
@@ -1,6 +1,9 @@
#version 310 es
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+const vec4 _66[2] = vec4[](vec4(10.0), vec4(30.0));
+const float _94[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
+
struct Composite
{
vec4 a[2];
@@ -25,13 +28,11 @@ vec4 summe(vec4 values[3][2])
void main()
{
vec4 values[2] = vec4[](_41.as[gl_GlobalInvocationID.x], _55.bs[gl_GlobalInvocationID.x]);
- vec4 const_values[2] = vec4[](vec4(10.0), vec4(30.0));
- vec4 copy_values[2] = const_values;
+ vec4 copy_values[2] = _66;
vec4 copy_values2[2] = values;
vec4 param[3][2] = vec4[][](values, copy_values, copy_values2);
_41.as[gl_GlobalInvocationID.x] = summe(param);
Composite c = Composite(values, copy_values);
- float arrayofarray[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
float b = 10.0;
float values_scalar[4] = float[](b, b, b, b);
}
diff --git a/deps/SPIRV-Cross/reference/shaders/flatten/copy.flatten.vert b/deps/SPIRV-Cross/reference/shaders/flatten/copy.flatten.vert
index 2bdd723886..6416a4f425 100644
--- a/deps/SPIRV-Cross/reference/shaders/flatten/copy.flatten.vert
+++ b/deps/SPIRV-Cross/reference/shaders/flatten/copy.flatten.vert
@@ -23,7 +23,7 @@ void main()
light.Radius = Light(UBO[i * 2 + 4].xyz, UBO[i * 2 + 4].w, UBO[i * 2 + 5]).Radius;
light.Color = Light(UBO[i * 2 + 4].xyz, UBO[i * 2 + 4].w, UBO[i * 2 + 5]).Color;
vec3 L = aVertex.xyz - light.Position;
- vColor += (((UBO[i * 2 + 5]) * clamp(1.0 - (length(L) / light.Radius), 0.0, 1.0)) * dot(aNormal, normalize(L)));
+ vColor += ((UBO[i * 2 + 5] * clamp(1.0 - (length(L) / light.Radius), 0.0, 1.0)) * dot(aNormal, normalize(L)));
}
}
diff --git a/deps/SPIRV-Cross/reference/shaders/flatten/dynamic.flatten.vert b/deps/SPIRV-Cross/reference/shaders/flatten/dynamic.flatten.vert
index 6214ca450a..8be397ea3f 100644
--- a/deps/SPIRV-Cross/reference/shaders/flatten/dynamic.flatten.vert
+++ b/deps/SPIRV-Cross/reference/shaders/flatten/dynamic.flatten.vert
@@ -18,8 +18,8 @@ void main()
vColor = vec4(0.0);
for (int i = 0; i < 4; i++)
{
- vec3 L = aVertex.xyz - (UBO[i * 2 + 4].xyz);
- vColor += (((UBO[i * 2 + 5]) * clamp(1.0 - (length(L) / (UBO[i * 2 + 4].w)), 0.0, 1.0)) * dot(aNormal, normalize(L)));
+ vec3 L = aVertex.xyz - UBO[i * 2 + 4].xyz;
+ vColor += ((UBO[i * 2 + 5] * clamp(1.0 - (length(L) / UBO[i * 2 + 4].w), 0.0, 1.0)) * dot(aNormal, normalize(L)));
}
}
diff --git a/deps/SPIRV-Cross/reference/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag b/deps/SPIRV-Cross/reference/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
index 21c3363ca6..ef6bb526ab 100644
--- a/deps/SPIRV-Cross/reference/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
+++ b/deps/SPIRV-Cross/reference/shaders/flatten/multi-dimensional.desktop.flatten_dim.frag
@@ -19,6 +19,6 @@ void main()
}
}
}
- FragColor = ((values3[1 * 3 * 1 + 2 * 1 + 0]) + (values3[0 * 3 * 1 + 2 * 1 + 0])) + (values3[(vIndex + 1) * 3 * 1 + 2 * 1 + vIndex]);
+ FragColor = (values3[1 * 3 * 1 + 2 * 1 + 0] + values3[0 * 3 * 1 + 2 * 1 + 0]) + values3[(vIndex + 1) * 3 * 1 + 2 * 1 + vIndex];
}
diff --git a/deps/SPIRV-Cross/reference/shaders/frag/array-lut-no-loop-variable.frag b/deps/SPIRV-Cross/reference/shaders/frag/array-lut-no-loop-variable.frag
index 54d7bf774c..baf2302519 100644
--- a/deps/SPIRV-Cross/reference/shaders/frag/array-lut-no-loop-variable.frag
+++ b/deps/SPIRV-Cross/reference/shaders/frag/array-lut-no-loop-variable.frag
@@ -2,12 +2,13 @@
precision mediump float;
precision highp int;
+const float _17[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
+
layout(location = 0) out vec4 FragColor;
void main()
{
- float lut[5] = float[](1.0, 2.0, 3.0, 4.0, 5.0);
- for (mediump int i = 0; i < 4; i++, FragColor += vec4(lut[i]))
+ for (mediump int i = 0; i < 4; i++, FragColor += vec4(_17[i]))
{
}
}
diff --git a/deps/SPIRV-Cross/reference/shaders/frag/constant-array.frag b/deps/SPIRV-Cross/reference/shaders/frag/constant-array.frag
index 4da9b8948b..be033f3873 100644
--- a/deps/SPIRV-Cross/reference/shaders/frag/constant-array.frag
+++ b/deps/SPIRV-Cross/reference/shaders/frag/constant-array.frag
@@ -2,6 +2,9 @@
precision mediump float;
precision highp int;
+const vec4 _37[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
+const vec4 _55[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
+
struct Foobar
{
float a;
@@ -18,11 +21,9 @@ vec4 resolve(Foobar f)
void main()
{
- highp vec4 indexable[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
- highp vec4 indexable_1[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
Foobar param = Foobar(10.0, 20.0);
- Foobar indexable_2[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
- Foobar param_1 = indexable_2[index];
- FragColor = ((indexable[index] + (indexable_1[index][index + 1])) + resolve(param)) + resolve(param_1);
+ Foobar indexable[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
+ Foobar param_1 = indexable[index];
+ FragColor = ((_37[index] + _55[index][index + 1]) + resolve(param)) + resolve(param_1);
}
diff --git a/deps/SPIRV-Cross/reference/shaders/frag/constant-composites.frag b/deps/SPIRV-Cross/reference/shaders/frag/constant-composites.frag
index b105dbd26c..c65c60613d 100644
--- a/deps/SPIRV-Cross/reference/shaders/frag/constant-composites.frag
+++ b/deps/SPIRV-Cross/reference/shaders/frag/constant-composites.frag
@@ -18,6 +18,6 @@ void main()
lut = float[](1.0, 4.0, 3.0, 2.0);
foos = Foo[](Foo(10.0, 20.0), Foo(30.0, 40.0));
FragColor = vec4(lut[line]);
- FragColor += vec4(foos[line].a * (foos[1 - line].a));
+ FragColor += vec4(foos[line].a * foos[1 - line].a);
}
diff --git a/deps/SPIRV-Cross/reference/shaders/frag/lut-promotion.frag b/deps/SPIRV-Cross/reference/shaders/frag/lut-promotion.frag
new file mode 100644
index 0000000000..019393f9f3
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/frag/lut-promotion.frag
@@ -0,0 +1,40 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+const float _16[16] = float[](1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
+const vec4 _60[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in mediump int index;
+
+void main()
+{
+ FragColor = _16[index];
+ if (index < 10)
+ {
+ FragColor += _16[index ^ 1];
+ }
+ else
+ {
+ FragColor += _16[index & 1];
+ }
+ if (index > 30)
+ {
+ FragColor += _60[index & 3].y;
+ }
+ else
+ {
+ FragColor += _60[index & 1].x;
+ }
+ vec4 foobar[4] = _60;
+ if (index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ FragColor += foobar[index & 3].z;
+ vec4 baz[4] = _60;
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[index & 3].z;
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag b/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag
new file mode 100644
index 0000000000..91b0331b79
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag
@@ -0,0 +1,9 @@
+#version 450
+
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = float((10u > 20u) ? 30u : 50u);
+}
+
diff --git a/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk b/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk
new file mode 100644
index 0000000000..59d3b99b9c
--- /dev/null
+++ b/deps/SPIRV-Cross/reference/shaders/vulkan/frag/spec-constant-ternary.vk.frag.vk
@@ -0,0 +1,13 @@
+#version 450
+
+layout(constant_id = 0) const uint s = 10u;
+const bool _13 = (s > 20u);
+const uint _16 = _13 ? 30u : 50u;
+
+layout(location = 0) out float FragColor;
+
+void main()
+{
+ FragColor = float(_16);
+}
+
diff --git a/deps/SPIRV-Cross/shaders-hlsl/asm/comp/control-flow-hints.asm.comp b/deps/SPIRV-Cross/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
new file mode 100644
index 0000000000..74a15955c2
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/asm/comp/control-flow-hints.asm.comp
@@ -0,0 +1,146 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 85
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %_main_ "@main("
+ OpName %i "i"
+ OpName %bar "bar"
+ OpMemberName %bar 0 "@data"
+ OpName %bar_0 "bar"
+ OpName %foo "foo"
+ OpName %i_0 "i"
+ OpName %v "v"
+ OpName %w "w"
+ OpName %value "value"
+ OpDecorate %_runtimearr_v4float ArrayStride 16
+ OpMemberDecorate %bar 0 Offset 0
+ OpDecorate %bar BufferBlock
+ OpDecorate %bar_0 DescriptorSet 0
+ OpDecorate %bar_0 Binding 0
+ OpDecorate %foo DescriptorSet 0
+ OpDecorate %foo Binding 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %int_16 = OpConstant %int 16
+ %bool = OpTypeBool
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+ %bar = OpTypeStruct %_runtimearr_v4float
+%_ptr_Uniform_bar = OpTypePointer Uniform %bar
+ %bar_0 = OpVariable %_ptr_Uniform_bar Uniform
+ %foo = OpVariable %_ptr_Uniform_bar Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+ %int_1 = OpConstant %int 1
+ %int_15 = OpConstant %int 15
+%_ptr_Function_float = OpTypePointer Function %float
+ %int_10 = OpConstant %int 10
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+ %float_10 = OpConstant %float 10
+ %int_20 = OpConstant %int 20
+ %float_5 = OpConstant %float 5
+ %72 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5
+ %float_20 = OpConstant %float 20
+ %float_40 = OpConstant %float 40
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %84 = OpFunctionCall %void %_main_
+ OpReturn
+ OpFunctionEnd
+ %_main_ = OpFunction %void None %3
+ %7 = OpLabel
+ %i = OpVariable %_ptr_Function_int Function
+ %i_0 = OpVariable %_ptr_Function_int Function
+ %v = OpVariable %_ptr_Function_float Function
+ %w = OpVariable %_ptr_Function_float Function
+ %value = OpVariable %_ptr_Function_float Function
+ OpStore %i %int_0
+ OpBranch %12
+ %12 = OpLabel
+ OpLoopMerge %14 %15 Unroll
+ OpBranch %16
+ %16 = OpLabel
+ %17 = OpLoad %int %i
+ %20 = OpSLessThan %bool %17 %int_16
+ OpBranchConditional %20 %13 %14
+ %13 = OpLabel
+ %27 = OpLoad %int %i
+ %29 = OpLoad %int %i
+ %31 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %29
+ %32 = OpLoad %v4float %31
+ %33 = OpAccessChain %_ptr_Uniform_v4float %bar_0 %int_0 %27
+ OpStore %33 %32
+ OpBranch %15
+ %15 = OpLabel
+ %34 = OpLoad %int %i
+ %36 = OpIAdd %int %34 %int_1
+ OpStore %i %36
+ OpBranch %12
+ %14 = OpLabel
+ OpStore %i_0 %int_0
+ OpBranch %38
+ %38 = OpLabel
+ OpLoopMerge %40 %41 DontUnroll
+ OpBranch %42
+ %42 = OpLabel
+ %43 = OpLoad %int %i_0
+ %44 = OpSLessThan %bool %43 %int_16
+ OpBranchConditional %44 %39 %40
+ %39 = OpLabel
+ %46 = OpLoad %int %i_0
+ %47 = OpISub %int %int_15 %46
+ %48 = OpLoad %int %i_0
+ %49 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %48
+ %50 = OpLoad %v4float %49
+ %51 = OpAccessChain %_ptr_Uniform_v4float %bar_0 %int_0 %47
+ OpStore %51 %50
+ OpBranch %41
+ %41 = OpLabel
+ %52 = OpLoad %int %i_0
+ %53 = OpIAdd %int %52 %int_1
+ OpStore %i_0 %53
+ OpBranch %38
+ %40 = OpLabel
+ %60 = OpAccessChain %_ptr_Uniform_float %bar_0 %int_0 %int_10 %uint_0
+ %61 = OpLoad %float %60
+ OpStore %v %61
+ %63 = OpAccessChain %_ptr_Uniform_float %foo %int_0 %int_10 %uint_0
+ %64 = OpLoad %float %63
+ OpStore %w %64
+ %65 = OpLoad %float %v
+ %67 = OpFOrdGreaterThan %bool %65 %float_10
+ OpSelectionMerge %69 DontFlatten
+ OpBranchConditional %67 %68 %69
+ %68 = OpLabel
+ %73 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %int_20
+ OpStore %73 %72
+ OpBranch %69
+ %69 = OpLabel
+ OpStore %value %float_20
+ %76 = OpLoad %float %w
+ %78 = OpFOrdGreaterThan %bool %76 %float_40
+ OpSelectionMerge %80 Flatten
+ OpBranchConditional %78 %79 %80
+ %79 = OpLabel
+ OpStore %value %float_20
+ OpBranch %80
+ %80 = OpLabel
+ %81 = OpLoad %float %value
+ %82 = OpCompositeConstruct %v4float %81 %81 %81 %81
+ %83 = OpAccessChain %_ptr_Uniform_v4float %foo %int_0 %int_20
+ OpStore %83 %82
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..320e5ebfbd
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,195 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 111
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %FragColor %index
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %FragColor "FragColor"
+ OpName %index "index"
+ OpName %indexable "indexable"
+ OpName %indexable_0 "indexable"
+ OpName %indexable_1 "indexable"
+ OpName %foo "foo"
+ OpName %foobar "foobar"
+ OpName %baz "baz"
+ OpDecorate %FragColor RelaxedPrecision
+ OpDecorate %FragColor Location 0
+ OpDecorate %index RelaxedPrecision
+ OpDecorate %index Flat
+ OpDecorate %index Location 0
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %25 RelaxedPrecision
+ OpDecorate %26 RelaxedPrecision
+ OpDecorate %32 RelaxedPrecision
+ OpDecorate %34 RelaxedPrecision
+ OpDecorate %37 RelaxedPrecision
+ OpDecorate %38 RelaxedPrecision
+ OpDecorate %39 RelaxedPrecision
+ OpDecorate %41 RelaxedPrecision
+ OpDecorate %42 RelaxedPrecision
+ OpDecorate %45 RelaxedPrecision
+ OpDecorate %46 RelaxedPrecision
+ OpDecorate %47 RelaxedPrecision
+ OpDecorate %foo RelaxedPrecision
+ OpDecorate %61 RelaxedPrecision
+ OpDecorate %66 RelaxedPrecision
+ OpDecorate %68 RelaxedPrecision
+ OpDecorate %71 RelaxedPrecision
+ OpDecorate %72 RelaxedPrecision
+ OpDecorate %73 RelaxedPrecision
+ OpDecorate %75 RelaxedPrecision
+ OpDecorate %76 RelaxedPrecision
+ OpDecorate %79 RelaxedPrecision
+ OpDecorate %80 RelaxedPrecision
+ OpDecorate %81 RelaxedPrecision
+ OpDecorate %foobar RelaxedPrecision
+ OpDecorate %83 RelaxedPrecision
+ OpDecorate %90 RelaxedPrecision
+ OpDecorate %91 RelaxedPrecision
+ OpDecorate %93 RelaxedPrecision
+ OpDecorate %94 RelaxedPrecision
+ OpDecorate %95 RelaxedPrecision
+ OpDecorate %baz RelaxedPrecision
+ OpDecorate %105 RelaxedPrecision
+ OpDecorate %106 RelaxedPrecision
+ OpDecorate %108 RelaxedPrecision
+ OpDecorate %109 RelaxedPrecision
+ OpDecorate %110 RelaxedPrecision
+ OpDecorate %16 RelaxedPrecision
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %uint = OpTypeInt 32 0
+ %uint_16 = OpConstant %uint 16
+%_arr_float_uint_16 = OpTypeArray %float %uint_16
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %16 = OpConstantComposite %_arr_float_uint_16 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+ %index = OpVariable %_ptr_Input_int Input
+%_ptr_Function__arr_float_uint_16 = OpTypePointer Function %_arr_float_uint_16
+%_ptr_Function_float = OpTypePointer Function %float
+ %int_10 = OpConstant %int 10
+ %bool = OpTypeBool
+ %int_1 = OpConstant %int 1
+ %v4float = OpTypeVector %float 4
+ %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+%_ptr_Function__arr_v4float_uint_4 = OpTypePointer Function %_arr_v4float_uint_4
+ %float_0 = OpConstant %float 0
+ %54 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %55 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %float_8 = OpConstant %float 8
+ %57 = OpConstantComposite %v4float %float_8 %float_8 %float_8 %float_8
+ %float_5 = OpConstant %float 5
+ %59 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5
+ %60 = OpConstantComposite %_arr_v4float_uint_4 %54 %55 %57 %59
+ %int_30 = OpConstant %int 30
+ %int_3 = OpConstant %int 3
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+ %float_20 = OpConstant %float 20
+ %uint_2 = OpConstant %uint 2
+ %97 = OpConstantComposite %v4float %float_20 %float_20 %float_20 %float_20
+ %float_30 = OpConstant %float 30
+ %99 = OpConstantComposite %v4float %float_30 %float_30 %float_30 %float_30
+ %float_50 = OpConstant %float 50
+ %101 = OpConstantComposite %v4float %float_50 %float_50 %float_50 %float_50
+ %float_60 = OpConstant %float 60
+ %103 = OpConstantComposite %v4float %float_60 %float_60 %float_60 %float_60
+ %104 = OpConstantComposite %_arr_v4float_uint_4 %97 %99 %101 %103
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %indexable = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_0 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_1 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+ %foo = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %foobar = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %baz = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %20 = OpLoad %int %index
+ %24 = OpAccessChain %_ptr_Function_float %indexable %20
+ %25 = OpLoad %float %24
+ OpStore %FragColor %25
+ %26 = OpLoad %int %index
+ %29 = OpSLessThan %bool %26 %int_10
+ OpSelectionMerge %31 None
+ OpBranchConditional %29 %30 %40
+ %30 = OpLabel
+ %32 = OpLoad %int %index
+ %34 = OpBitwiseXor %int %32 %int_1
+ %36 = OpAccessChain %_ptr_Function_float %indexable_0 %34
+ %37 = OpLoad %float %36
+ %38 = OpLoad %float %FragColor
+ %39 = OpFAdd %float %38 %37
+ OpStore %FragColor %39
+ OpBranch %31
+ %40 = OpLabel
+ %41 = OpLoad %int %index
+ %42 = OpBitwiseAnd %int %41 %int_1
+ %44 = OpAccessChain %_ptr_Function_float %indexable_1 %42
+ %45 = OpLoad %float %44
+ %46 = OpLoad %float %FragColor
+ %47 = OpFAdd %float %46 %45
+ OpStore %FragColor %47
+ OpBranch %31
+ %31 = OpLabel
+ %61 = OpLoad %int %index
+ %63 = OpSGreaterThan %bool %61 %int_30
+ OpSelectionMerge %65 None
+ OpBranchConditional %63 %64 %74
+ %64 = OpLabel
+ %66 = OpLoad %int %index
+ %68 = OpBitwiseAnd %int %66 %int_3
+ %70 = OpAccessChain %_ptr_Function_float %foo %68 %uint_1
+ %71 = OpLoad %float %70
+ %72 = OpLoad %float %FragColor
+ %73 = OpFAdd %float %72 %71
+ OpStore %FragColor %73
+ OpBranch %65
+ %74 = OpLabel
+ %75 = OpLoad %int %index
+ %76 = OpBitwiseAnd %int %75 %int_1
+ %78 = OpAccessChain %_ptr_Function_float %foo %76 %uint_0
+ %79 = OpLoad %float %78
+ %80 = OpLoad %float %FragColor
+ %81 = OpFAdd %float %80 %79
+ OpStore %FragColor %81
+ OpBranch %65
+ %65 = OpLabel
+ %83 = OpLoad %int %index
+ %84 = OpSGreaterThan %bool %83 %int_30
+ OpSelectionMerge %86 None
+ OpBranchConditional %84 %85 %86
+ %85 = OpLabel
+ %89 = OpAccessChain %_ptr_Function_float %foobar %int_1 %uint_2
+ OpStore %89 %float_20
+ OpBranch %86
+ %86 = OpLabel
+ %90 = OpLoad %int %index
+ %91 = OpBitwiseAnd %int %90 %int_3
+ %92 = OpAccessChain %_ptr_Function_float %foobar %91 %uint_2
+ %93 = OpLoad %float %92
+ %94 = OpLoad %float %FragColor
+ %95 = OpFAdd %float %94 %93
+ OpStore %FragColor %95
+ OpStore %baz %104
+ %105 = OpLoad %int %index
+ %106 = OpBitwiseAnd %int %105 %int_3
+ %107 = OpAccessChain %_ptr_Function_float %baz %106 %uint_2
+ %108 = OpLoad %float %107
+ %109 = OpLoad %float %FragColor
+ %110 = OpFAdd %float %109 %108
+ OpStore %FragColor %110
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..89036f0eb2
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %vUV %FragColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %sample_combined_ "sample_combined("
+ OpName %sample_separate_ "sample_separate("
+ OpName %uShadow "uShadow"
+ OpName %vUV "vUV"
+ OpName %uTexture "uTexture"
+ OpName %uSampler "uSampler"
+ OpName %FragColor "FragColor"
+ OpDecorate %uShadow DescriptorSet 0
+ OpDecorate %uShadow Binding 0
+ OpDecorate %vUV Location 0
+ OpDecorate %uTexture DescriptorSet 0
+ OpDecorate %uTexture Binding 1
+ OpDecorate %uSampler DescriptorSet 0
+ OpDecorate %uSampler Binding 2
+ OpDecorate %FragColor Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %7 = OpTypeFunction %float
+ %12 = OpTypeImage %float 2D 2 0 0 1 Unknown
+ %13 = OpTypeSampledImage %12
+%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
+ %uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+ %vUV = OpVariable %_ptr_Input_v3float Input
+%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
+ %uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
+ %29 = OpTypeSampler
+%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
+ %uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %41 = OpFunctionCall %float %sample_combined_
+ %42 = OpFunctionCall %float %sample_separate_
+ %43 = OpFAdd %float %41 %42
+ OpStore %FragColor %43
+ OpReturn
+ OpFunctionEnd
+%sample_combined_ = OpFunction %float None %7
+ %9 = OpLabel
+ %16 = OpLoad %13 %uShadow
+ %20 = OpLoad %v3float %vUV
+ %21 = OpCompositeExtract %float %20 2
+ %22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
+ OpReturnValue %22
+ OpFunctionEnd
+%sample_separate_ = OpFunction %float None %7
+ %11 = OpLabel
+ %28 = OpLoad %12 %uTexture
+ %32 = OpLoad %29 %uSampler
+ %33 = OpSampledImage %13 %28 %32
+ %34 = OpLoad %v3float %vUV
+ %35 = OpCompositeExtract %float %34 2
+ %36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
+ OpReturnValue %36
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..29b0076a1e
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %_main_u1_u1_ "@main(u1;u1;"
+ OpName %vid "vid"
+ OpName %iid "iid"
+ OpName %vid_0 "vid"
+ OpName %vid_1 "vid"
+ OpName %iid_0 "iid"
+ OpName %iid_1 "iid"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpName %param "param"
+ OpName %param_0 "param"
+ OpDecorate %vid_1 BuiltIn VertexIndex
+ OpDecorate %iid_1 BuiltIn InstanceIndex
+ OpDecorate %_entryPointOutput BuiltIn Position
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %vid_1 = OpVariable %_ptr_Input_uint Input
+ %iid_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %vid_0 = OpVariable %_ptr_Function_uint Function
+ %iid_0 = OpVariable %_ptr_Function_uint Function
+ %param = OpVariable %_ptr_Function_uint Function
+ %param_0 = OpVariable %_ptr_Function_uint Function
+ %25 = OpLoad %uint %vid_1
+ OpStore %vid_0 %25
+ %28 = OpLoad %uint %iid_1
+ OpStore %iid_0 %28
+ %32 = OpLoad %uint %vid_0
+ OpStore %param %32
+ %34 = OpLoad %uint %iid_0
+ OpStore %param_0 %34
+ %35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
+ OpStore %_entryPointOutput %35
+ OpReturn
+ OpFunctionEnd
+%_main_u1_u1_ = OpFunction %v4float None %10
+ %vid = OpFunctionParameter %_ptr_Function_uint
+ %iid = OpFunctionParameter %_ptr_Function_uint
+ %14 = OpLabel
+ %15 = OpLoad %uint %vid
+ %16 = OpLoad %uint %iid
+ %17 = OpIAdd %uint %15 %16
+ %18 = OpConvertUToF %float %17
+ %19 = OpCompositeConstruct %v4float %18 %18 %18 %18
+ OpReturnValue %19
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-hlsl/comp/globallycoherent.comp b/deps/SPIRV-Cross/shaders-hlsl/comp/globallycoherent.comp
new file mode 100644
index 0000000000..168b9404ea
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/comp/globallycoherent.comp
@@ -0,0 +1,25 @@
+#version 450
+layout(local_size_x = 1) in;
+
+layout(r32f, binding = 0) uniform readonly image2D uImageIn;
+layout(r32f, binding = 1) uniform coherent writeonly image2D uImageOut;
+
+layout(set = 0, binding = 2) readonly buffer Foo
+{
+ float foo;
+};
+
+layout(set = 0, binding = 3) coherent writeonly buffer Bar
+{
+ float bar;
+};
+
+void main()
+{
+ ivec2 coord = ivec2(9, 7);
+ vec4 indata = imageLoad(uImageIn, coord);
+ imageStore(uImageOut, coord, indata);
+
+ bar = foo;
+}
+
diff --git a/deps/SPIRV-Cross/shaders-hlsl/frag/lut-promotion.frag b/deps/SPIRV-Cross/shaders-hlsl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..0cdc8148f9
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/frag/lut-promotion.frag
@@ -0,0 +1,44 @@
+#version 310 es
+precision mediump float;
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in int index;
+
+const float LUT[16] = float[](
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0);
+
+void main()
+{
+ // Try reading LUTs, both in branches and not branch.
+ FragColor = LUT[index];
+ if (index < 10)
+ FragColor += LUT[index ^ 1];
+ else
+ FragColor += LUT[index & 1];
+
+ // Not declared as a LUT, but can be promoted to one.
+ vec4 foo[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ FragColor += foo[index & 3].y;
+ }
+ else
+ {
+ FragColor += foo[index & 1].x;
+ }
+
+ // Not declared as a LUT, but this cannot be promoted, because we have a partial write.
+ vec4 foobar[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ FragColor += foobar[index & 3].z;
+
+ // Not declared as a LUT, but this cannot be promoted, because we have two complete writes.
+ vec4 baz[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[index & 3].z;
+}
diff --git a/deps/SPIRV-Cross/shaders-hlsl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/shaders-hlsl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..78dccbf044
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-hlsl/frag/spec-constant-ternary.frag
@@ -0,0 +1,9 @@
+#version 450
+layout(location = 0) out float FragColor;
+layout(constant_id = 0) const uint s = 10u;
+const uint f = s > 20u ? 30u : 50u;
+
+void main()
+{
+ FragColor = float(f);
+}
diff --git a/deps/SPIRV-Cross/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..320e5ebfbd
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,195 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 111
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %FragColor %index
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %FragColor "FragColor"
+ OpName %index "index"
+ OpName %indexable "indexable"
+ OpName %indexable_0 "indexable"
+ OpName %indexable_1 "indexable"
+ OpName %foo "foo"
+ OpName %foobar "foobar"
+ OpName %baz "baz"
+ OpDecorate %FragColor RelaxedPrecision
+ OpDecorate %FragColor Location 0
+ OpDecorate %index RelaxedPrecision
+ OpDecorate %index Flat
+ OpDecorate %index Location 0
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %25 RelaxedPrecision
+ OpDecorate %26 RelaxedPrecision
+ OpDecorate %32 RelaxedPrecision
+ OpDecorate %34 RelaxedPrecision
+ OpDecorate %37 RelaxedPrecision
+ OpDecorate %38 RelaxedPrecision
+ OpDecorate %39 RelaxedPrecision
+ OpDecorate %41 RelaxedPrecision
+ OpDecorate %42 RelaxedPrecision
+ OpDecorate %45 RelaxedPrecision
+ OpDecorate %46 RelaxedPrecision
+ OpDecorate %47 RelaxedPrecision
+ OpDecorate %foo RelaxedPrecision
+ OpDecorate %61 RelaxedPrecision
+ OpDecorate %66 RelaxedPrecision
+ OpDecorate %68 RelaxedPrecision
+ OpDecorate %71 RelaxedPrecision
+ OpDecorate %72 RelaxedPrecision
+ OpDecorate %73 RelaxedPrecision
+ OpDecorate %75 RelaxedPrecision
+ OpDecorate %76 RelaxedPrecision
+ OpDecorate %79 RelaxedPrecision
+ OpDecorate %80 RelaxedPrecision
+ OpDecorate %81 RelaxedPrecision
+ OpDecorate %foobar RelaxedPrecision
+ OpDecorate %83 RelaxedPrecision
+ OpDecorate %90 RelaxedPrecision
+ OpDecorate %91 RelaxedPrecision
+ OpDecorate %93 RelaxedPrecision
+ OpDecorate %94 RelaxedPrecision
+ OpDecorate %95 RelaxedPrecision
+ OpDecorate %baz RelaxedPrecision
+ OpDecorate %105 RelaxedPrecision
+ OpDecorate %106 RelaxedPrecision
+ OpDecorate %108 RelaxedPrecision
+ OpDecorate %109 RelaxedPrecision
+ OpDecorate %110 RelaxedPrecision
+ OpDecorate %16 RelaxedPrecision
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %uint = OpTypeInt 32 0
+ %uint_16 = OpConstant %uint 16
+%_arr_float_uint_16 = OpTypeArray %float %uint_16
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %16 = OpConstantComposite %_arr_float_uint_16 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+ %index = OpVariable %_ptr_Input_int Input
+%_ptr_Function__arr_float_uint_16 = OpTypePointer Function %_arr_float_uint_16
+%_ptr_Function_float = OpTypePointer Function %float
+ %int_10 = OpConstant %int 10
+ %bool = OpTypeBool
+ %int_1 = OpConstant %int 1
+ %v4float = OpTypeVector %float 4
+ %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+%_ptr_Function__arr_v4float_uint_4 = OpTypePointer Function %_arr_v4float_uint_4
+ %float_0 = OpConstant %float 0
+ %54 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %55 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %float_8 = OpConstant %float 8
+ %57 = OpConstantComposite %v4float %float_8 %float_8 %float_8 %float_8
+ %float_5 = OpConstant %float 5
+ %59 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5
+ %60 = OpConstantComposite %_arr_v4float_uint_4 %54 %55 %57 %59
+ %int_30 = OpConstant %int 30
+ %int_3 = OpConstant %int 3
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+ %float_20 = OpConstant %float 20
+ %uint_2 = OpConstant %uint 2
+ %97 = OpConstantComposite %v4float %float_20 %float_20 %float_20 %float_20
+ %float_30 = OpConstant %float 30
+ %99 = OpConstantComposite %v4float %float_30 %float_30 %float_30 %float_30
+ %float_50 = OpConstant %float 50
+ %101 = OpConstantComposite %v4float %float_50 %float_50 %float_50 %float_50
+ %float_60 = OpConstant %float 60
+ %103 = OpConstantComposite %v4float %float_60 %float_60 %float_60 %float_60
+ %104 = OpConstantComposite %_arr_v4float_uint_4 %97 %99 %101 %103
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %indexable = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_0 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_1 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+ %foo = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %foobar = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %baz = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %20 = OpLoad %int %index
+ %24 = OpAccessChain %_ptr_Function_float %indexable %20
+ %25 = OpLoad %float %24
+ OpStore %FragColor %25
+ %26 = OpLoad %int %index
+ %29 = OpSLessThan %bool %26 %int_10
+ OpSelectionMerge %31 None
+ OpBranchConditional %29 %30 %40
+ %30 = OpLabel
+ %32 = OpLoad %int %index
+ %34 = OpBitwiseXor %int %32 %int_1
+ %36 = OpAccessChain %_ptr_Function_float %indexable_0 %34
+ %37 = OpLoad %float %36
+ %38 = OpLoad %float %FragColor
+ %39 = OpFAdd %float %38 %37
+ OpStore %FragColor %39
+ OpBranch %31
+ %40 = OpLabel
+ %41 = OpLoad %int %index
+ %42 = OpBitwiseAnd %int %41 %int_1
+ %44 = OpAccessChain %_ptr_Function_float %indexable_1 %42
+ %45 = OpLoad %float %44
+ %46 = OpLoad %float %FragColor
+ %47 = OpFAdd %float %46 %45
+ OpStore %FragColor %47
+ OpBranch %31
+ %31 = OpLabel
+ %61 = OpLoad %int %index
+ %63 = OpSGreaterThan %bool %61 %int_30
+ OpSelectionMerge %65 None
+ OpBranchConditional %63 %64 %74
+ %64 = OpLabel
+ %66 = OpLoad %int %index
+ %68 = OpBitwiseAnd %int %66 %int_3
+ %70 = OpAccessChain %_ptr_Function_float %foo %68 %uint_1
+ %71 = OpLoad %float %70
+ %72 = OpLoad %float %FragColor
+ %73 = OpFAdd %float %72 %71
+ OpStore %FragColor %73
+ OpBranch %65
+ %74 = OpLabel
+ %75 = OpLoad %int %index
+ %76 = OpBitwiseAnd %int %75 %int_1
+ %78 = OpAccessChain %_ptr_Function_float %foo %76 %uint_0
+ %79 = OpLoad %float %78
+ %80 = OpLoad %float %FragColor
+ %81 = OpFAdd %float %80 %79
+ OpStore %FragColor %81
+ OpBranch %65
+ %65 = OpLabel
+ %83 = OpLoad %int %index
+ %84 = OpSGreaterThan %bool %83 %int_30
+ OpSelectionMerge %86 None
+ OpBranchConditional %84 %85 %86
+ %85 = OpLabel
+ %89 = OpAccessChain %_ptr_Function_float %foobar %int_1 %uint_2
+ OpStore %89 %float_20
+ OpBranch %86
+ %86 = OpLabel
+ %90 = OpLoad %int %index
+ %91 = OpBitwiseAnd %int %90 %int_3
+ %92 = OpAccessChain %_ptr_Function_float %foobar %91 %uint_2
+ %93 = OpLoad %float %92
+ %94 = OpLoad %float %FragColor
+ %95 = OpFAdd %float %94 %93
+ OpStore %FragColor %95
+ OpStore %baz %104
+ %105 = OpLoad %int %index
+ %106 = OpBitwiseAnd %int %105 %int_3
+ %107 = OpAccessChain %_ptr_Function_float %baz %106 %uint_2
+ %108 = OpLoad %float %107
+ %109 = OpLoad %float %FragColor
+ %110 = OpFAdd %float %109 %108
+ OpStore %FragColor %110
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-msl/asm/frag/unknown-depth-state.asm.frag b/deps/SPIRV-Cross/shaders-msl/asm/frag/unknown-depth-state.asm.frag
new file mode 100644
index 0000000000..89036f0eb2
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/asm/frag/unknown-depth-state.asm.frag
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %vUV %FragColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %sample_combined_ "sample_combined("
+ OpName %sample_separate_ "sample_separate("
+ OpName %uShadow "uShadow"
+ OpName %vUV "vUV"
+ OpName %uTexture "uTexture"
+ OpName %uSampler "uSampler"
+ OpName %FragColor "FragColor"
+ OpDecorate %uShadow DescriptorSet 0
+ OpDecorate %uShadow Binding 0
+ OpDecorate %vUV Location 0
+ OpDecorate %uTexture DescriptorSet 0
+ OpDecorate %uTexture Binding 1
+ OpDecorate %uSampler DescriptorSet 0
+ OpDecorate %uSampler Binding 2
+ OpDecorate %FragColor Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %7 = OpTypeFunction %float
+ %12 = OpTypeImage %float 2D 2 0 0 1 Unknown
+ %13 = OpTypeSampledImage %12
+%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
+ %uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+ %vUV = OpVariable %_ptr_Input_v3float Input
+%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
+ %uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
+ %29 = OpTypeSampler
+%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
+ %uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %41 = OpFunctionCall %float %sample_combined_
+ %42 = OpFunctionCall %float %sample_separate_
+ %43 = OpFAdd %float %41 %42
+ OpStore %FragColor %43
+ OpReturn
+ OpFunctionEnd
+%sample_combined_ = OpFunction %float None %7
+ %9 = OpLabel
+ %16 = OpLoad %13 %uShadow
+ %20 = OpLoad %v3float %vUV
+ %21 = OpCompositeExtract %float %20 2
+ %22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
+ OpReturnValue %22
+ OpFunctionEnd
+%sample_separate_ = OpFunction %float None %7
+ %11 = OpLabel
+ %28 = OpLoad %12 %uTexture
+ %32 = OpLoad %29 %uSampler
+ %33 = OpSampledImage %13 %28 %32
+ %34 = OpLoad %v3float %vUV
+ %35 = OpCompositeExtract %float %34 2
+ %36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
+ OpReturnValue %36
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..29b0076a1e
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %_main_u1_u1_ "@main(u1;u1;"
+ OpName %vid "vid"
+ OpName %iid "iid"
+ OpName %vid_0 "vid"
+ OpName %vid_1 "vid"
+ OpName %iid_0 "iid"
+ OpName %iid_1 "iid"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpName %param "param"
+ OpName %param_0 "param"
+ OpDecorate %vid_1 BuiltIn VertexIndex
+ OpDecorate %iid_1 BuiltIn InstanceIndex
+ OpDecorate %_entryPointOutput BuiltIn Position
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %vid_1 = OpVariable %_ptr_Input_uint Input
+ %iid_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %vid_0 = OpVariable %_ptr_Function_uint Function
+ %iid_0 = OpVariable %_ptr_Function_uint Function
+ %param = OpVariable %_ptr_Function_uint Function
+ %param_0 = OpVariable %_ptr_Function_uint Function
+ %25 = OpLoad %uint %vid_1
+ OpStore %vid_0 %25
+ %28 = OpLoad %uint %iid_1
+ OpStore %iid_0 %28
+ %32 = OpLoad %uint %vid_0
+ OpStore %param %32
+ %34 = OpLoad %uint %iid_0
+ OpStore %param_0 %34
+ %35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
+ OpStore %_entryPointOutput %35
+ OpReturn
+ OpFunctionEnd
+%_main_u1_u1_ = OpFunction %v4float None %10
+ %vid = OpFunctionParameter %_ptr_Function_uint
+ %iid = OpFunctionParameter %_ptr_Function_uint
+ %14 = OpLabel
+ %15 = OpLoad %uint %vid
+ %16 = OpLoad %uint %iid
+ %17 = OpIAdd %uint %15 %16
+ %18 = OpConvertUToF %float %17
+ %19 = OpCompositeConstruct %v4float %18 %18 %18 %18
+ OpReturnValue %19
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-msl/frag/lut-promotion.frag b/deps/SPIRV-Cross/shaders-msl/frag/lut-promotion.frag
new file mode 100644
index 0000000000..0cdc8148f9
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/frag/lut-promotion.frag
@@ -0,0 +1,44 @@
+#version 310 es
+precision mediump float;
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in int index;
+
+const float LUT[16] = float[](
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0);
+
+void main()
+{
+ // Try reading LUTs, both in branches and not branch.
+ FragColor = LUT[index];
+ if (index < 10)
+ FragColor += LUT[index ^ 1];
+ else
+ FragColor += LUT[index & 1];
+
+ // Not declared as a LUT, but can be promoted to one.
+ vec4 foo[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ FragColor += foo[index & 3].y;
+ }
+ else
+ {
+ FragColor += foo[index & 1].x;
+ }
+
+ // Not declared as a LUT, but this cannot be promoted, because we have a partial write.
+ vec4 foobar[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ FragColor += foobar[index & 3].z;
+
+ // Not declared as a LUT, but this cannot be promoted, because we have two complete writes.
+ vec4 baz[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[index & 3].z;
+}
diff --git a/deps/SPIRV-Cross/shaders-msl/frag/spec-constant-ternary.frag b/deps/SPIRV-Cross/shaders-msl/frag/spec-constant-ternary.frag
new file mode 100644
index 0000000000..78dccbf044
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/frag/spec-constant-ternary.frag
@@ -0,0 +1,9 @@
+#version 450
+layout(location = 0) out float FragColor;
+layout(constant_id = 0) const uint s = 10u;
+const uint f = s > 20u ? 30u : 50u;
+
+void main()
+{
+ FragColor = float(f);
+}
diff --git a/deps/SPIRV-Cross/shaders-msl/vert/set_builtin_in_func.vert b/deps/SPIRV-Cross/shaders-msl/vert/set_builtin_in_func.vert
new file mode 100644
index 0000000000..dd991e3545
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-msl/vert/set_builtin_in_func.vert
@@ -0,0 +1,12 @@
+#version 450
+
+void write_outblock()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(gl_PointSize);
+}
+
+void main()
+{
+ write_outblock();
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/asm/aliased-entry-point-names.asm.multi b/deps/SPIRV-Cross/shaders-reflection/asm/aliased-entry-point-names.asm.multi
new file mode 100644
index 0000000000..d60cf3039c
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/asm/aliased-entry-point-names.asm.multi
@@ -0,0 +1,60 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 3
+; Bound: 20
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %_
+ OpEntryPoint Vertex %main2 "main2" %_
+ OpEntryPoint Fragment %main3 "main" %FragColor
+ OpEntryPoint Fragment %main4 "main2" %FragColor
+ OpSource GLSL 450
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %FragColor Location 0
+ OpDecorate %gl_PerVertex Block
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %v4floatptr = OpTypePointer Output %v4float
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+ %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+ %FragColor = OpVariable %v4floatptr Output
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %float_1 = OpConstant %float 1
+ %17 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %float_2 = OpConstant %float 2
+ %18 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %19 %17
+ OpReturn
+ OpFunctionEnd
+ %main2 = OpFunction %void None %3
+ %6 = OpLabel
+ %20 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+ OpStore %20 %18
+ OpReturn
+ OpFunctionEnd
+ %main3 = OpFunction %void None %3
+ %7 = OpLabel
+ OpStore %FragColor %17
+ OpReturn
+ OpFunctionEnd
+ %main4 = OpFunction %void None %3
+ %8 = OpLabel
+ OpStore %FragColor %18
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-reflection/comp/struct-layout.comp b/deps/SPIRV-Cross/shaders-reflection/comp/struct-layout.comp
new file mode 100644
index 0000000000..5a2b7802df
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/comp/struct-layout.comp
@@ -0,0 +1,24 @@
+#version 310 es
+layout(local_size_x = 1) in;
+
+struct Foo
+{
+ mat4 m;
+};
+
+layout(std430, binding = 0) readonly buffer SSBO
+{
+ Foo in_data[];
+};
+
+layout(std430, binding = 1) writeonly buffer SSBO2
+{
+ Foo out_data[];
+};
+
+void main()
+{
+ uint ident = gl_GlobalInvocationID.x;
+ out_data[ident].m = in_data[ident].m * in_data[ident].m;
+}
+
diff --git a/deps/SPIRV-Cross/shaders-reflection/comp/struct-packing.comp b/deps/SPIRV-Cross/shaders-reflection/comp/struct-packing.comp
new file mode 100644
index 0000000000..d2ffbaef50
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/comp/struct-packing.comp
@@ -0,0 +1,87 @@
+#version 450
+
+layout(local_size_x = 1) in;
+
+struct S0
+{
+ vec2 a[1];
+ float b;
+};
+
+struct S1
+{
+ vec3 a;
+ float b;
+};
+
+struct S2
+{
+ vec3 a[1];
+ float b;
+};
+
+struct S3
+{
+ vec2 a;
+ float b;
+};
+
+struct S4
+{
+ vec2 c;
+};
+
+struct Content
+{
+ S0 m0s[1];
+ S1 m1s[1];
+ S2 m2s[1];
+ S0 m0;
+ S1 m1;
+ S2 m2;
+ S3 m3;
+ float m4;
+
+ S4 m3s[8];
+};
+
+layout(binding = 1, std430) restrict buffer SSBO1
+{
+ Content content;
+ Content content1[2];
+ Content content2;
+
+ layout(column_major) mat2 m0;
+ layout(column_major) mat2 m1;
+ layout(column_major) mat2x3 m2[4];
+ layout(column_major) mat3x2 m3;
+ layout(row_major) mat2 m4;
+ layout(row_major) mat2 m5[9];
+ layout(row_major) mat2x3 m6[4][2];
+ layout(row_major) mat3x2 m7;
+ float array[];
+} ssbo_430;
+
+layout(binding = 0, std140) restrict buffer SSBO0
+{
+ Content content;
+ Content content1[2];
+ Content content2;
+
+ layout(column_major) mat2 m0;
+ layout(column_major) mat2 m1;
+ layout(column_major) mat2x3 m2[4];
+ layout(column_major) mat3x2 m3;
+ layout(row_major) mat2 m4;
+ layout(row_major) mat2 m5[9];
+ layout(row_major) mat2x3 m6[4][2];
+ layout(row_major) mat3x2 m7;
+
+ float array[];
+} ssbo_140;
+
+void main()
+{
+ ssbo_430.content = ssbo_140.content;
+}
+
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag
new file mode 100644
index 0000000000..2fabb5ea8a
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler-shadow.vk.frag
@@ -0,0 +1,29 @@
+#version 310 es
+precision mediump float;
+
+layout(set = 0, binding = 0) uniform mediump samplerShadow uSampler;
+layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
+layout(set = 0, binding = 2) uniform texture2D uDepth;
+layout(location = 0) out float FragColor;
+
+float samp2(texture2D t, mediump samplerShadow s)
+{
+ return texture(sampler2DShadow(t, s), vec3(1.0));
+}
+
+float samp3(texture2D t, mediump sampler s)
+{
+ return texture(sampler2D(t, s), vec2(1.0)).x;
+}
+
+float samp(texture2D t, mediump samplerShadow s, mediump sampler s1)
+{
+ float r0 = samp2(t, s);
+ float r1 = samp3(t, s1);
+ return r0 + r1;
+}
+
+void main()
+{
+ FragColor = samp(uDepth, uSampler, uSampler1);
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler.vk.frag
new file mode 100644
index 0000000000..b7de8d47e9
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/combined-texture-sampler.vk.frag
@@ -0,0 +1,47 @@
+#version 310 es
+precision mediump float;
+
+layout(set = 0, binding = 0) uniform mediump sampler uSampler0;
+layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
+layout(set = 0, binding = 2) uniform mediump texture2D uTexture0;
+layout(set = 0, binding = 3) uniform mediump texture2D uTexture1;
+
+layout(location = 0) out vec4 FragColor;
+layout(location = 0) in vec2 vTex;
+
+vec4 sample_dual(mediump sampler samp, mediump texture2D tex)
+{
+ return texture(sampler2D(tex, samp), vTex);
+}
+
+vec4 sample_global_tex(mediump sampler samp)
+{
+ vec4 a = texture(sampler2D(uTexture0, samp), vTex);
+ vec4 b = sample_dual(samp, uTexture1);
+ return a + b;
+}
+
+vec4 sample_global_sampler(mediump texture2D tex)
+{
+ vec4 a = texture(sampler2D(tex, uSampler0), vTex);
+ vec4 b = sample_dual(uSampler1, tex);
+ return a + b;
+}
+
+vec4 sample_duals()
+{
+ vec4 a = sample_dual(uSampler0, uTexture0);
+ vec4 b = sample_dual(uSampler1, uTexture1);
+ return a + b;
+}
+
+void main()
+{
+ vec4 c0 = sample_duals();
+ vec4 c1 = sample_global_tex(uSampler0);
+ vec4 c2 = sample_global_tex(uSampler1);
+ vec4 c3 = sample_global_sampler(uTexture0);
+ vec4 c4 = sample_global_sampler(uTexture1);
+
+ FragColor = c0 + c1 + c2 + c3 + c4;
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/image-load-store-uint-coord.asm.frag b/deps/SPIRV-Cross/shaders-reflection/frag/image-load-store-uint-coord.asm.frag
new file mode 100644
index 0000000000..a9bf1a7497
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/image-load-store-uint-coord.asm.frag
@@ -0,0 +1,103 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 2
+; Bound: 63
+; Schema: 0
+ OpCapability Shader
+ OpCapability SampledBuffer
+ OpCapability ImageBuffer
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %_entryPointOutput
+ OpExecutionMode %main OriginUpperLeft
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %_main_ "@main("
+ OpName %storeTemp "storeTemp"
+ OpName %RWIm "RWIm"
+ OpName %v "v"
+ OpName %RWBuf "RWBuf"
+ OpName %ROIm "ROIm"
+ OpName %ROBuf "ROBuf"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpDecorate %RWIm DescriptorSet 0
+ OpDecorate %RWIm Binding 1
+ OpDecorate %RWBuf DescriptorSet 0
+ OpDecorate %RWBuf Binding 0
+ OpDecorate %ROIm DescriptorSet 0
+ OpDecorate %ROIm Binding 1
+ OpDecorate %ROBuf DescriptorSet 0
+ OpDecorate %ROBuf Binding 0
+ OpDecorate %_entryPointOutput Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %8 = OpTypeFunction %v4float
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+ %float_10 = OpConstant %float 10
+ %float_0_5 = OpConstant %float 0.5
+ %float_8 = OpConstant %float 8
+ %float_2 = OpConstant %float 2
+ %17 = OpConstantComposite %v4float %float_10 %float_0_5 %float_8 %float_2
+ %18 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
+%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
+ %RWIm = OpVariable %_ptr_UniformConstant_18 UniformConstant
+ %uint = OpTypeInt 32 0
+ %v2uint = OpTypeVector %uint 2
+ %uint_10 = OpConstant %uint 10
+ %25 = OpConstantComposite %v2uint %uint_10 %uint_10
+ %uint_30 = OpConstant %uint 30
+ %30 = OpConstantComposite %v2uint %uint_30 %uint_30
+ %32 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f
+%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32
+ %RWBuf = OpVariable %_ptr_UniformConstant_32 UniformConstant
+ %uint_80 = OpConstant %uint 80
+ %38 = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %SampledImage = OpTypeSampledImage %38
+%_ptr_UniformConstant_38 = OpTypePointer UniformConstant %SampledImage
+ %ROIm = OpVariable %_ptr_UniformConstant_38 UniformConstant
+ %uint_50 = OpConstant %uint 50
+ %uint_60 = OpConstant %uint 60
+ %44 = OpConstantComposite %v2uint %uint_50 %uint_60
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %50 = OpTypeImage %float Buffer 0 0 0 1 Rgba32f
+%_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50
+ %ROBuf = OpVariable %_ptr_UniformConstant_50 UniformConstant
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %62 = OpFunctionCall %v4float %_main_
+ OpStore %_entryPointOutput %62
+ OpReturn
+ OpFunctionEnd
+ %_main_ = OpFunction %v4float None %8
+ %10 = OpLabel
+ %storeTemp = OpVariable %_ptr_Function_v4float Function
+ %v = OpVariable %_ptr_Function_v4float Function
+ OpStore %storeTemp %17
+ %21 = OpLoad %18 %RWIm
+ %26 = OpLoad %v4float %storeTemp
+ OpImageWrite %21 %25 %26
+ %28 = OpLoad %18 %RWIm
+ %31 = OpImageRead %v4float %28 %30
+ OpStore %v %31
+ %35 = OpLoad %32 %RWBuf
+ %37 = OpLoad %v4float %v
+ OpImageWrite %35 %uint_80 %37
+ %41 = OpLoad %SampledImage %ROIm
+ %ROImage = OpImage %38 %41
+ %47 = OpImageFetch %v4float %ROImage %44 Lod %int_0
+ %48 = OpLoad %v4float %v
+ %49 = OpFAdd %v4float %48 %47
+ OpStore %v %49
+ %53 = OpLoad %50 %ROBuf
+ %54 = OpImageFetch %v4float %53 %uint_80
+ %55 = OpLoad %v4float %v
+ %56 = OpFAdd %v4float %55 %54
+ OpStore %v %56
+ %57 = OpLoad %v4float %v
+ OpReturnValue %57
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment-ms.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment-ms.vk.frag
new file mode 100644
index 0000000000..e060738846
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment-ms.vk.frag
@@ -0,0 +1,10 @@
+#version 450
+
+layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS uSubpass0;
+layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInputMS uSubpass1;
+layout(location = 0) out vec4 FragColor;
+
+void main()
+{
+ FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2) + subpassLoad(uSubpass0, gl_SampleID);
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment.vk.frag
new file mode 100644
index 0000000000..f082d15b2a
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/input-attachment.vk.frag
@@ -0,0 +1,11 @@
+#version 310 es
+precision mediump float;
+
+layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInput uSubpass0;
+layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInput uSubpass1;
+layout(location = 0) out vec4 FragColor;
+
+void main()
+{
+ FragColor = subpassLoad(uSubpass0) + subpassLoad(uSubpass1);
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/push-constant.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/push-constant.vk.frag
new file mode 100644
index 0000000000..6180faba31
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/push-constant.vk.frag
@@ -0,0 +1,16 @@
+#version 310 es
+precision mediump float;
+
+layout(push_constant, std430) uniform PushConstants
+{
+ vec4 value0;
+ vec4 value1;
+} push;
+
+layout(location = 0) in vec4 vColor;
+layout(location = 0) out vec4 FragColor;
+
+void main()
+{
+ FragColor = vColor + push.value0 + push.value1;
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/separate-sampler-texture-array.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/separate-sampler-texture-array.vk.frag
new file mode 100644
index 0000000000..b3501c1d8d
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/separate-sampler-texture-array.vk.frag
@@ -0,0 +1,42 @@
+#version 310 es
+precision mediump float;
+
+layout(set = 0, binding = 0) uniform mediump sampler uSampler;
+layout(set = 0, binding = 1) uniform mediump texture2D uTexture[4];
+layout(set = 0, binding = 2) uniform mediump texture3D uTexture3D[4];
+layout(set = 0, binding = 3) uniform mediump textureCube uTextureCube[4];
+layout(set = 0, binding = 4) uniform mediump texture2DArray uTextureArray[4];
+
+layout(location = 0) out vec4 FragColor;
+layout(location = 0) in vec2 vTex;
+layout(location = 1) in vec3 vTex3;
+
+vec4 sample_func(mediump sampler samp, vec2 uv)
+{
+ return texture(sampler2D(uTexture[2], samp), uv);
+}
+
+vec4 sample_func_dual(mediump sampler samp, mediump texture2D tex, vec2 uv)
+{
+ return texture(sampler2D(tex, samp), uv);
+}
+
+vec4 sample_func_dual_array(mediump sampler samp, mediump texture2D tex[4], vec2 uv)
+{
+ return texture(sampler2D(tex[1], samp), uv);
+}
+
+void main()
+{
+ vec2 off = 1.0 / vec2(textureSize(sampler2D(uTexture[1], uSampler), 0));
+ vec2 off2 = 1.0 / vec2(textureSize(sampler2D(uTexture[2], uSampler), 1));
+
+ vec4 c0 = sample_func(uSampler, vTex + off + off2);
+ vec4 c1 = sample_func_dual(uSampler, uTexture[1], vTex + off + off2);
+ vec4 c2 = sample_func_dual_array(uSampler, uTexture, vTex + off + off2);
+ vec4 c3 = texture(sampler2DArray(uTextureArray[3], uSampler), vTex3);
+ vec4 c4 = texture(samplerCube(uTextureCube[1], uSampler), vTex3);
+ vec4 c5 = texture(sampler3D(uTexture3D[2], uSampler), vTex3);
+
+ FragColor = c0 + c1 + c2 + c3 + c4 + c5;
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/frag/spec-constant.vk.frag b/deps/SPIRV-Cross/shaders-reflection/frag/spec-constant.vk.frag
new file mode 100644
index 0000000000..e62a26059b
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/frag/spec-constant.vk.frag
@@ -0,0 +1,78 @@
+#version 310 es
+precision mediump float;
+
+layout(location = 0) out vec4 FragColor;
+layout(constant_id = 1) const float a = 1.5;
+layout(constant_id = 2) const float b = 2.5;
+layout(constant_id = 3) const int c = 3;
+layout(constant_id = 4) const int d = 4;
+layout(constant_id = 5) const uint e = 5u;
+layout(constant_id = 6) const uint f = 6u;
+layout(constant_id = 7) const bool g = false;
+layout(constant_id = 8) const bool h = true;
+
+// glslang doesn't seem to support partial spec constants or composites yet, so only test the basics.
+
+struct Foo
+{
+ float elems[d + 2];
+};
+
+void main()
+{
+ float t0 = a;
+ float t1 = b;
+
+ uint c0 = uint(c); // OpIAdd with different types.
+ // FConvert, float-to-double.
+ int c1 = -c; // SNegate
+ int c2 = ~c; // OpNot
+ int c3 = c + d; // OpIAdd
+ int c4 = c - d; // OpISub
+ int c5 = c * d; // OpIMul
+ int c6 = c / d; // OpSDiv
+ uint c7 = e / f; // OpUDiv
+ int c8 = c % d; // OpSMod
+ uint c9 = e % f; // OpUMod
+ // TODO: OpSRem, any way to access this in GLSL?
+ int c10 = c >> d; // OpShiftRightArithmetic
+ uint c11 = e >> f; // OpShiftRightLogical
+ int c12 = c << d; // OpShiftLeftLogical
+ int c13 = c | d; // OpBitwiseOr
+ int c14 = c ^ d; // OpBitwiseXor
+ int c15 = c & d; // OpBitwiseAnd
+ // VectorShuffle, CompositeExtract, CompositeInsert, not testable atm.
+ bool c16 = g || h; // OpLogicalOr
+ bool c17 = g && h; // OpLogicalAnd
+ bool c18 = !g; // OpLogicalNot
+ bool c19 = g == h; // OpLogicalEqual
+ bool c20 = g != h; // OpLogicalNotEqual
+ // OpSelect not testable atm.
+ bool c21 = c == d; // OpIEqual
+ bool c22 = c != d; // OpINotEqual
+ bool c23 = c < d; // OpSLessThan
+ bool c24 = e < f; // OpULessThan
+ bool c25 = c > d; // OpSGreaterThan
+ bool c26 = e > f; // OpUGreaterThan
+ bool c27 = c <= d; // OpSLessThanEqual
+ bool c28 = e <= f; // OpULessThanEqual
+ bool c29 = c >= d; // OpSGreaterThanEqual
+ bool c30 = e >= f; // OpUGreaterThanEqual
+ // OpQuantizeToF16 not testable atm.
+
+ int c31 = c8 + c3;
+
+ int c32 = int(e); // OpIAdd with different types.
+ bool c33 = bool(c); // int -> bool
+ bool c34 = bool(e); // uint -> bool
+ int c35 = int(g); // bool -> int
+ uint c36 = uint(g); // bool -> uint
+ float c37 = float(g); // bool -> float
+
+ // Flexible sized arrays with spec constants and spec constant ops.
+ float vec0[c + 3][8];
+ float vec1[c + 2];
+
+ Foo foo;
+ FragColor = vec4(t0 + t1) + vec0[0][0] + vec1[0] + foo.elems[c];
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/vert/read-from-row-major-array.vert b/deps/SPIRV-Cross/shaders-reflection/vert/read-from-row-major-array.vert
new file mode 100644
index 0000000000..792fb8e36c
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/vert/read-from-row-major-array.vert
@@ -0,0 +1,20 @@
+#version 310 es
+layout(location = 0) in highp vec4 a_position;
+layout(location = 0) out mediump float v_vtxResult;
+
+layout(set = 0, binding = 0, std140, row_major) uniform Block
+{
+ highp mat2x3 var[3][4];
+};
+
+mediump float compare_float (highp float a, highp float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }
+mediump float compare_vec3 (highp vec3 a, highp vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }
+mediump float compare_mat2x3 (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }
+
+void main (void)
+{
+ gl_Position = a_position;
+ mediump float result = 1.0;
+ result *= compare_mat2x3(var[0][0], mat2x3(2.0, 6.0, -6.0, 0.0, 5.0, 5.0));
+ v_vtxResult = result;
+}
diff --git a/deps/SPIRV-Cross/shaders-reflection/vert/texture_buffer.vert b/deps/SPIRV-Cross/shaders-reflection/vert/texture_buffer.vert
new file mode 100644
index 0000000000..6bc7ddfae2
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders-reflection/vert/texture_buffer.vert
@@ -0,0 +1,10 @@
+#version 310 es
+#extension GL_OES_texture_buffer : require
+
+layout(binding = 4) uniform highp samplerBuffer uSamp;
+layout(rgba32f, binding = 5) uniform readonly highp imageBuffer uSampo;
+
+void main()
+{
+ gl_Position = texelFetch(uSamp, 10) + imageLoad(uSampo, 100);
+}
diff --git a/deps/SPIRV-Cross/shaders/asm/frag/lut-promotion-initializer.asm.frag b/deps/SPIRV-Cross/shaders/asm/frag/lut-promotion-initializer.asm.frag
new file mode 100644
index 0000000000..320e5ebfbd
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/asm/frag/lut-promotion-initializer.asm.frag
@@ -0,0 +1,195 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 111
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %FragColor %index
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %FragColor "FragColor"
+ OpName %index "index"
+ OpName %indexable "indexable"
+ OpName %indexable_0 "indexable"
+ OpName %indexable_1 "indexable"
+ OpName %foo "foo"
+ OpName %foobar "foobar"
+ OpName %baz "baz"
+ OpDecorate %FragColor RelaxedPrecision
+ OpDecorate %FragColor Location 0
+ OpDecorate %index RelaxedPrecision
+ OpDecorate %index Flat
+ OpDecorate %index Location 0
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %25 RelaxedPrecision
+ OpDecorate %26 RelaxedPrecision
+ OpDecorate %32 RelaxedPrecision
+ OpDecorate %34 RelaxedPrecision
+ OpDecorate %37 RelaxedPrecision
+ OpDecorate %38 RelaxedPrecision
+ OpDecorate %39 RelaxedPrecision
+ OpDecorate %41 RelaxedPrecision
+ OpDecorate %42 RelaxedPrecision
+ OpDecorate %45 RelaxedPrecision
+ OpDecorate %46 RelaxedPrecision
+ OpDecorate %47 RelaxedPrecision
+ OpDecorate %foo RelaxedPrecision
+ OpDecorate %61 RelaxedPrecision
+ OpDecorate %66 RelaxedPrecision
+ OpDecorate %68 RelaxedPrecision
+ OpDecorate %71 RelaxedPrecision
+ OpDecorate %72 RelaxedPrecision
+ OpDecorate %73 RelaxedPrecision
+ OpDecorate %75 RelaxedPrecision
+ OpDecorate %76 RelaxedPrecision
+ OpDecorate %79 RelaxedPrecision
+ OpDecorate %80 RelaxedPrecision
+ OpDecorate %81 RelaxedPrecision
+ OpDecorate %foobar RelaxedPrecision
+ OpDecorate %83 RelaxedPrecision
+ OpDecorate %90 RelaxedPrecision
+ OpDecorate %91 RelaxedPrecision
+ OpDecorate %93 RelaxedPrecision
+ OpDecorate %94 RelaxedPrecision
+ OpDecorate %95 RelaxedPrecision
+ OpDecorate %baz RelaxedPrecision
+ OpDecorate %105 RelaxedPrecision
+ OpDecorate %106 RelaxedPrecision
+ OpDecorate %108 RelaxedPrecision
+ OpDecorate %109 RelaxedPrecision
+ OpDecorate %110 RelaxedPrecision
+ OpDecorate %16 RelaxedPrecision
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %uint = OpTypeInt 32 0
+ %uint_16 = OpConstant %uint 16
+%_arr_float_uint_16 = OpTypeArray %float %uint_16
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %16 = OpConstantComposite %_arr_float_uint_16 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4 %float_1 %float_2 %float_3 %float_4
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+ %index = OpVariable %_ptr_Input_int Input
+%_ptr_Function__arr_float_uint_16 = OpTypePointer Function %_arr_float_uint_16
+%_ptr_Function_float = OpTypePointer Function %float
+ %int_10 = OpConstant %int 10
+ %bool = OpTypeBool
+ %int_1 = OpConstant %int 1
+ %v4float = OpTypeVector %float 4
+ %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+%_ptr_Function__arr_v4float_uint_4 = OpTypePointer Function %_arr_v4float_uint_4
+ %float_0 = OpConstant %float 0
+ %54 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %55 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %float_8 = OpConstant %float 8
+ %57 = OpConstantComposite %v4float %float_8 %float_8 %float_8 %float_8
+ %float_5 = OpConstant %float 5
+ %59 = OpConstantComposite %v4float %float_5 %float_5 %float_5 %float_5
+ %60 = OpConstantComposite %_arr_v4float_uint_4 %54 %55 %57 %59
+ %int_30 = OpConstant %int 30
+ %int_3 = OpConstant %int 3
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+ %float_20 = OpConstant %float 20
+ %uint_2 = OpConstant %uint 2
+ %97 = OpConstantComposite %v4float %float_20 %float_20 %float_20 %float_20
+ %float_30 = OpConstant %float 30
+ %99 = OpConstantComposite %v4float %float_30 %float_30 %float_30 %float_30
+ %float_50 = OpConstant %float 50
+ %101 = OpConstantComposite %v4float %float_50 %float_50 %float_50 %float_50
+ %float_60 = OpConstant %float 60
+ %103 = OpConstantComposite %v4float %float_60 %float_60 %float_60 %float_60
+ %104 = OpConstantComposite %_arr_v4float_uint_4 %97 %99 %101 %103
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %indexable = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_0 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+%indexable_1 = OpVariable %_ptr_Function__arr_float_uint_16 Function %16
+ %foo = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %foobar = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %baz = OpVariable %_ptr_Function__arr_v4float_uint_4 Function %60
+ %20 = OpLoad %int %index
+ %24 = OpAccessChain %_ptr_Function_float %indexable %20
+ %25 = OpLoad %float %24
+ OpStore %FragColor %25
+ %26 = OpLoad %int %index
+ %29 = OpSLessThan %bool %26 %int_10
+ OpSelectionMerge %31 None
+ OpBranchConditional %29 %30 %40
+ %30 = OpLabel
+ %32 = OpLoad %int %index
+ %34 = OpBitwiseXor %int %32 %int_1
+ %36 = OpAccessChain %_ptr_Function_float %indexable_0 %34
+ %37 = OpLoad %float %36
+ %38 = OpLoad %float %FragColor
+ %39 = OpFAdd %float %38 %37
+ OpStore %FragColor %39
+ OpBranch %31
+ %40 = OpLabel
+ %41 = OpLoad %int %index
+ %42 = OpBitwiseAnd %int %41 %int_1
+ %44 = OpAccessChain %_ptr_Function_float %indexable_1 %42
+ %45 = OpLoad %float %44
+ %46 = OpLoad %float %FragColor
+ %47 = OpFAdd %float %46 %45
+ OpStore %FragColor %47
+ OpBranch %31
+ %31 = OpLabel
+ %61 = OpLoad %int %index
+ %63 = OpSGreaterThan %bool %61 %int_30
+ OpSelectionMerge %65 None
+ OpBranchConditional %63 %64 %74
+ %64 = OpLabel
+ %66 = OpLoad %int %index
+ %68 = OpBitwiseAnd %int %66 %int_3
+ %70 = OpAccessChain %_ptr_Function_float %foo %68 %uint_1
+ %71 = OpLoad %float %70
+ %72 = OpLoad %float %FragColor
+ %73 = OpFAdd %float %72 %71
+ OpStore %FragColor %73
+ OpBranch %65
+ %74 = OpLabel
+ %75 = OpLoad %int %index
+ %76 = OpBitwiseAnd %int %75 %int_1
+ %78 = OpAccessChain %_ptr_Function_float %foo %76 %uint_0
+ %79 = OpLoad %float %78
+ %80 = OpLoad %float %FragColor
+ %81 = OpFAdd %float %80 %79
+ OpStore %FragColor %81
+ OpBranch %65
+ %65 = OpLabel
+ %83 = OpLoad %int %index
+ %84 = OpSGreaterThan %bool %83 %int_30
+ OpSelectionMerge %86 None
+ OpBranchConditional %84 %85 %86
+ %85 = OpLabel
+ %89 = OpAccessChain %_ptr_Function_float %foobar %int_1 %uint_2
+ OpStore %89 %float_20
+ OpBranch %86
+ %86 = OpLabel
+ %90 = OpLoad %int %index
+ %91 = OpBitwiseAnd %int %90 %int_3
+ %92 = OpAccessChain %_ptr_Function_float %foobar %91 %uint_2
+ %93 = OpLoad %float %92
+ %94 = OpLoad %float %FragColor
+ %95 = OpFAdd %float %94 %93
+ OpStore %FragColor %95
+ OpStore %baz %104
+ %105 = OpLoad %int %index
+ %106 = OpBitwiseAnd %int %105 %int_3
+ %107 = OpAccessChain %_ptr_Function_float %baz %106 %uint_2
+ %108 = OpLoad %float %107
+ %109 = OpLoad %float %FragColor
+ %110 = OpFAdd %float %109 %108
+ OpStore %FragColor %110
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders/asm/frag/switch-label-shared-block.asm.frag b/deps/SPIRV-Cross/shaders/asm/frag/switch-label-shared-block.asm.frag
new file mode 100644
index 0000000000..8f55bcf536
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/asm/frag/switch-label-shared-block.asm.frag
@@ -0,0 +1,45 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %vIndex %FragColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %vIndex "vIndex"
+ OpName %FragColor "FragColor"
+ OpDecorate %vIndex RelaxedPrecision
+ OpDecorate %vIndex Flat
+ OpDecorate %vIndex Location 0
+ OpDecorate %13 RelaxedPrecision
+ OpDecorate %FragColor RelaxedPrecision
+ OpDecorate %FragColor Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %float_8 = OpConstant %float 8
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+ %vIndex = OpVariable %_ptr_Input_int Input
+ %float_1 = OpConstant %float 1
+ %float_3 = OpConstant %float 3
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %13 = OpLoad %int %vIndex
+ OpSelectionMerge %17 None
+ OpSwitch %13 %15 0 %14 2 %14 1 %15 8 %17
+ %15 = OpLabel
+ OpBranch %17
+ %14 = OpLabel
+ OpBranch %17
+ %17 = OpLabel
+ %27 = OpPhi %float %float_3 %15 %float_1 %14 %float_8 %5
+ OpStore %FragColor %27
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders/asm/frag/unknown-depth-state.asm.vk.frag b/deps/SPIRV-Cross/shaders/asm/frag/unknown-depth-state.asm.vk.frag
new file mode 100644
index 0000000000..89036f0eb2
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/asm/frag/unknown-depth-state.asm.vk.frag
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %vUV %FragColor
+ OpExecutionMode %main OriginUpperLeft
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %sample_combined_ "sample_combined("
+ OpName %sample_separate_ "sample_separate("
+ OpName %uShadow "uShadow"
+ OpName %vUV "vUV"
+ OpName %uTexture "uTexture"
+ OpName %uSampler "uSampler"
+ OpName %FragColor "FragColor"
+ OpDecorate %uShadow DescriptorSet 0
+ OpDecorate %uShadow Binding 0
+ OpDecorate %vUV Location 0
+ OpDecorate %uTexture DescriptorSet 0
+ OpDecorate %uTexture Binding 1
+ OpDecorate %uSampler DescriptorSet 0
+ OpDecorate %uSampler Binding 2
+ OpDecorate %FragColor Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %7 = OpTypeFunction %float
+ %12 = OpTypeImage %float 2D 2 0 0 1 Unknown
+ %13 = OpTypeSampledImage %12
+%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
+ %uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+ %vUV = OpVariable %_ptr_Input_v3float Input
+%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
+ %uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
+ %29 = OpTypeSampler
+%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
+ %uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
+%_ptr_Output_float = OpTypePointer Output %float
+ %FragColor = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %41 = OpFunctionCall %float %sample_combined_
+ %42 = OpFunctionCall %float %sample_separate_
+ %43 = OpFAdd %float %41 %42
+ OpStore %FragColor %43
+ OpReturn
+ OpFunctionEnd
+%sample_combined_ = OpFunction %float None %7
+ %9 = OpLabel
+ %16 = OpLoad %13 %uShadow
+ %20 = OpLoad %v3float %vUV
+ %21 = OpCompositeExtract %float %20 2
+ %22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
+ OpReturnValue %22
+ OpFunctionEnd
+%sample_separate_ = OpFunction %float None %7
+ %11 = OpLabel
+ %28 = OpLoad %12 %uTexture
+ %32 = OpLoad %29 %uSampler
+ %33 = OpSampledImage %13 %28 %32
+ %34 = OpLoad %v3float %vUV
+ %35 = OpCompositeExtract %float %34 2
+ %36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
+ OpReturnValue %36
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders/asm/geom/store-uint-layer.invalid.asm.geom b/deps/SPIRV-Cross/shaders/asm/geom/store-uint-layer.invalid.asm.geom
new file mode 100644
index 0000000000..550fc4e990
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/asm/geom/store-uint-layer.invalid.asm.geom
@@ -0,0 +1,130 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 74
+; Schema: 0
+ OpCapability Geometry
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Geometry %main "main" %stream_pos %stream_layer %input_pos
+ OpExecutionMode %main Triangles
+ OpExecutionMode %main Invocations 1
+ OpExecutionMode %main OutputTriangleStrip
+ OpExecutionMode %main OutputVertices 3
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %VertexOutput "VertexOutput"
+ OpMemberName %VertexOutput 0 "pos"
+ OpName %GeometryOutput "GeometryOutput"
+ OpMemberName %GeometryOutput 0 "pos"
+ OpMemberName %GeometryOutput 1 "layer"
+ OpName %_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ "@main(struct-VertexOutput-vf41[3];struct-GeometryOutput-vf4-u11;"
+ OpName %input "input"
+ OpName %stream "stream"
+ OpName %output "output"
+ OpName %v "v"
+ OpName %stream_pos "stream.pos"
+ OpName %stream_layer "stream.layer"
+ OpName %input_0 "input"
+ OpName %input_pos "input.pos"
+ OpName %stream_0 "stream"
+ OpName %param "param"
+ OpName %param_0 "param"
+ OpDecorate %stream_pos BuiltIn Position
+ OpDecorate %stream_layer BuiltIn Layer
+ OpDecorate %input_pos BuiltIn Position
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%VertexOutput = OpTypeStruct %v4float
+ %uint = OpTypeInt 32 0
+ %uint_3 = OpConstant %uint 3
+%_arr_VertexOutput_uint_3 = OpTypeArray %VertexOutput %uint_3
+%_ptr_Function__arr_VertexOutput_uint_3 = OpTypePointer Function %_arr_VertexOutput_uint_3
+%GeometryOutput = OpTypeStruct %v4float %uint
+%_ptr_Function_GeometryOutput = OpTypePointer Function %GeometryOutput
+ %15 = OpTypeFunction %void %_ptr_Function__arr_VertexOutput_uint_3 %_ptr_Function_GeometryOutput
+ %int = OpTypeInt 32 1
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_0 = OpConstant %int 0
+ %int_3 = OpConstant %int 3
+ %bool = OpTypeBool
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %stream_pos = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_uint = OpTypePointer Output %uint
+%stream_layer = OpVariable %_ptr_Output_uint Output
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+%_ptr_Input__arr_v4float_uint_3 = OpTypePointer Input %_arr_v4float_uint_3
+ %input_pos = OpVariable %_ptr_Input__arr_v4float_uint_3 Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+ %int_2 = OpConstant %int 2
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %input_0 = OpVariable %_ptr_Function__arr_VertexOutput_uint_3 Function
+ %stream_0 = OpVariable %_ptr_Function_GeometryOutput Function
+ %param = OpVariable %_ptr_Function__arr_VertexOutput_uint_3 Function
+ %param_0 = OpVariable %_ptr_Function_GeometryOutput Function
+ %58 = OpAccessChain %_ptr_Input_v4float %input_pos %int_0
+ %59 = OpLoad %v4float %58
+ %60 = OpAccessChain %_ptr_Function_v4float %input_0 %int_0 %int_0
+ OpStore %60 %59
+ %61 = OpAccessChain %_ptr_Input_v4float %input_pos %int_1
+ %62 = OpLoad %v4float %61
+ %63 = OpAccessChain %_ptr_Function_v4float %input_0 %int_1 %int_0
+ OpStore %63 %62
+ %65 = OpAccessChain %_ptr_Input_v4float %input_pos %int_2
+ %66 = OpLoad %v4float %65
+ %67 = OpAccessChain %_ptr_Function_v4float %input_0 %int_2 %int_0
+ OpStore %67 %66
+ %70 = OpLoad %_arr_VertexOutput_uint_3 %input_0
+ OpStore %param %70
+ %72 = OpFunctionCall %void %_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ %param %param_0
+ %73 = OpLoad %GeometryOutput %param_0
+ OpStore %stream_0 %73
+ OpReturn
+ OpFunctionEnd
+%_main_struct_VertexOutput_vf41_3__struct_GeometryOutput_vf4_u11_ = OpFunction %void None %15
+ %input = OpFunctionParameter %_ptr_Function__arr_VertexOutput_uint_3
+ %stream = OpFunctionParameter %_ptr_Function_GeometryOutput
+ %19 = OpLabel
+ %output = OpVariable %_ptr_Function_GeometryOutput Function
+ %v = OpVariable %_ptr_Function_int Function
+ %25 = OpAccessChain %_ptr_Function_uint %output %int_1
+ OpStore %25 %uint_1
+ OpStore %v %int_0
+ OpBranch %29
+ %29 = OpLabel
+ OpLoopMerge %31 %32 None
+ OpBranch %33
+ %33 = OpLabel
+ %34 = OpLoad %int %v
+ %37 = OpSLessThan %bool %34 %int_3
+ OpBranchConditional %37 %30 %31
+ %30 = OpLabel
+ %38 = OpLoad %int %v
+ %40 = OpAccessChain %_ptr_Function_v4float %input %38 %int_0
+ %41 = OpLoad %v4float %40
+ %42 = OpAccessChain %_ptr_Function_v4float %output %int_0
+ OpStore %42 %41
+ %45 = OpAccessChain %_ptr_Function_v4float %output %int_0
+ %46 = OpLoad %v4float %45
+ OpStore %stream_pos %46
+ %49 = OpAccessChain %_ptr_Function_uint %output %int_1
+ %50 = OpLoad %uint %49
+ OpStore %stream_layer %50
+ OpEmitVertex
+ OpBranch %32
+ %32 = OpLabel
+ %51 = OpLoad %int %v
+ %52 = OpIAdd %int %51 %int_1
+ OpStore %v %52
+ OpBranch %29
+ %31 = OpLabel
+ OpEndPrimitive
+ OpReturn
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert b/deps/SPIRV-Cross/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
new file mode 100644
index 0000000000..29b0076a1e
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/asm/vert/uint-vertex-id-instance-id.asm.vert
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 6
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %vid_1 %iid_1 %_entryPointOutput
+ OpSource HLSL 500
+ OpName %main "main"
+ OpName %_main_u1_u1_ "@main(u1;u1;"
+ OpName %vid "vid"
+ OpName %iid "iid"
+ OpName %vid_0 "vid"
+ OpName %vid_1 "vid"
+ OpName %iid_0 "iid"
+ OpName %iid_1 "iid"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpName %param "param"
+ OpName %param_0 "param"
+ OpDecorate %vid_1 BuiltIn VertexIndex
+ OpDecorate %iid_1 BuiltIn InstanceIndex
+ OpDecorate %_entryPointOutput BuiltIn Position
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %10 = OpTypeFunction %v4float %_ptr_Function_uint %_ptr_Function_uint
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %vid_1 = OpVariable %_ptr_Input_uint Input
+ %iid_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %vid_0 = OpVariable %_ptr_Function_uint Function
+ %iid_0 = OpVariable %_ptr_Function_uint Function
+ %param = OpVariable %_ptr_Function_uint Function
+ %param_0 = OpVariable %_ptr_Function_uint Function
+ %25 = OpLoad %uint %vid_1
+ OpStore %vid_0 %25
+ %28 = OpLoad %uint %iid_1
+ OpStore %iid_0 %28
+ %32 = OpLoad %uint %vid_0
+ OpStore %param %32
+ %34 = OpLoad %uint %iid_0
+ OpStore %param_0 %34
+ %35 = OpFunctionCall %v4float %_main_u1_u1_ %param %param_0
+ OpStore %_entryPointOutput %35
+ OpReturn
+ OpFunctionEnd
+%_main_u1_u1_ = OpFunction %v4float None %10
+ %vid = OpFunctionParameter %_ptr_Function_uint
+ %iid = OpFunctionParameter %_ptr_Function_uint
+ %14 = OpLabel
+ %15 = OpLoad %uint %vid
+ %16 = OpLoad %uint %iid
+ %17 = OpIAdd %uint %15 %16
+ %18 = OpConvertUToF %float %17
+ %19 = OpCompositeConstruct %v4float %18 %18 %18 %18
+ OpReturnValue %19
+ OpFunctionEnd
diff --git a/deps/SPIRV-Cross/shaders/frag/lut-promotion.frag b/deps/SPIRV-Cross/shaders/frag/lut-promotion.frag
new file mode 100644
index 0000000000..0cdc8148f9
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/frag/lut-promotion.frag
@@ -0,0 +1,44 @@
+#version 310 es
+precision mediump float;
+layout(location = 0) out float FragColor;
+layout(location = 0) flat in int index;
+
+const float LUT[16] = float[](
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0,
+ 1.0, 2.0, 3.0, 4.0);
+
+void main()
+{
+ // Try reading LUTs, both in branches and not branch.
+ FragColor = LUT[index];
+ if (index < 10)
+ FragColor += LUT[index ^ 1];
+ else
+ FragColor += LUT[index & 1];
+
+ // Not declared as a LUT, but can be promoted to one.
+ vec4 foo[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ FragColor += foo[index & 3].y;
+ }
+ else
+ {
+ FragColor += foo[index & 1].x;
+ }
+
+ // Not declared as a LUT, but this cannot be promoted, because we have a partial write.
+ vec4 foobar[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ if (index > 30)
+ {
+ foobar[1].z = 20.0;
+ }
+ FragColor += foobar[index & 3].z;
+
+ // Not declared as a LUT, but this cannot be promoted, because we have two complete writes.
+ vec4 baz[4] = vec4[](vec4(0.0), vec4(1.0), vec4(8.0), vec4(5.0));
+ baz = vec4[](vec4(20.0), vec4(30.0), vec4(50.0), vec4(60.0));
+ FragColor += baz[index & 3].z;
+}
diff --git a/deps/SPIRV-Cross/shaders/vulkan/frag/spec-constant-ternary.vk.frag b/deps/SPIRV-Cross/shaders/vulkan/frag/spec-constant-ternary.vk.frag
new file mode 100644
index 0000000000..78dccbf044
--- /dev/null
+++ b/deps/SPIRV-Cross/shaders/vulkan/frag/spec-constant-ternary.vk.frag
@@ -0,0 +1,9 @@
+#version 450
+layout(location = 0) out float FragColor;
+layout(constant_id = 0) const uint s = 10u;
+const uint f = s > 20u ? 30u : 50u;
+
+void main()
+{
+ FragColor = float(f);
+}
diff --git a/deps/SPIRV-Cross/spirv_common.hpp b/deps/SPIRV-Cross/spirv_common.hpp
index c4716a2388..0ea94fcb0c 100644
--- a/deps/SPIRV-Cross/spirv_common.hpp
+++ b/deps/SPIRV-Cross/spirv_common.hpp
@@ -578,6 +578,15 @@ struct SPIRBlock : IVariant
MergeSelection
};
+ enum Hints
+ {
+ HintNone,
+ HintUnroll,
+ HintDontUnroll,
+ HintFlatten,
+ HintDontFlatten
+ };
+
enum Method
{
MergeToSelectForLoop,
@@ -610,6 +619,7 @@ struct SPIRBlock : IVariant
Terminator terminator = Unknown;
Merge merge = MergeNone;
+ Hints hint = HintNone;
uint32_t next_block = 0;
uint32_t merge_block = 0;
uint32_t continue_block = 0;
@@ -754,7 +764,6 @@ struct SPIRFunction : IVariant
bool active = false;
bool flush_undeclared = true;
bool do_combined_parameters = true;
- bool analyzed_variable_scope = false;
};
struct SPIRAccessChain : IVariant
@@ -1092,6 +1101,9 @@ struct SPIRConstant : IVariant
// If this constant is used as an array length which creates specialization restrictions on some backends.
bool is_used_as_array_length = false;
+ // If true, this is a LUT, and should always be declared in the outer scope.
+ bool is_used_as_lut = false;
+
// For composites which are constant arrays, etc.
std::vector subconstants;
};
diff --git a/deps/SPIRV-Cross/spirv_cpp.cpp b/deps/SPIRV-Cross/spirv_cpp.cpp
index 9302a07441..7d781e9172 100644
--- a/deps/SPIRV-Cross/spirv_cpp.cpp
+++ b/deps/SPIRV-Cross/spirv_cpp.cpp
@@ -300,6 +300,7 @@ string CompilerCPP::compile()
backend.explicit_struct_type = true;
backend.use_initializer_list = true;
+ build_function_control_flow_graphs_and_analyze();
update_active_builtins();
uint32_t pass_count = 0;
diff --git a/deps/SPIRV-Cross/spirv_cross.cpp b/deps/SPIRV-Cross/spirv_cross.cpp
index 0402562e0b..dd2a44ca33 100644
--- a/deps/SPIRV-Cross/spirv_cross.cpp
+++ b/deps/SPIRV-Cross/spirv_cross.cpp
@@ -1063,6 +1063,34 @@ const SPIRType &Compiler::get_type_from_variable(uint32_t id) const
return get(get(id).basetype);
}
+uint32_t Compiler::get_non_pointer_type_id(uint32_t type_id) const
+{
+ auto *p_type = &get(type_id);
+ while (p_type->pointer)
+ {
+ assert(p_type->parent_type);
+ type_id = p_type->parent_type;
+ p_type = &get(type_id);
+ }
+ return type_id;
+}
+
+const SPIRType &Compiler::get_non_pointer_type(const SPIRType &type) const
+{
+ auto *p_type = &type;
+ while (p_type->pointer)
+ {
+ assert(p_type->parent_type);
+ p_type = &get(p_type->parent_type);
+ }
+ return *p_type;
+}
+
+const SPIRType &Compiler::get_non_pointer_type(uint32_t type_id) const
+{
+ return get_non_pointer_type(get(type_id));
+}
+
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,
const std::string &argument)
{
@@ -1814,7 +1842,7 @@ void Compiler::parse(const Instruction &instruction)
type.basetype = SPIRType::Image;
type.image.type = ops[1];
type.image.dim = static_cast(ops[2]);
- type.image.depth = ops[3] != 0;
+ type.image.depth = ops[3] == 1;
type.image.arrayed = ops[4] != 0;
type.image.ms = ops[5] != 0;
type.image.sampled = ops[6];
@@ -2221,6 +2249,14 @@ void Compiler::parse(const Instruction &instruction)
current_block->next_block = ops[0];
current_block->merge = SPIRBlock::MergeSelection;
selection_merge_targets.insert(current_block->next_block);
+
+ if (length >= 2)
+ {
+ if (ops[1] & SelectionControlFlattenMask)
+ current_block->hint = SPIRBlock::HintFlatten;
+ else if (ops[1] & SelectionControlDontFlattenMask)
+ current_block->hint = SPIRBlock::HintDontFlatten;
+ }
break;
}
@@ -2243,6 +2279,14 @@ void Compiler::parse(const Instruction &instruction)
// they are treated as continues.
if (current_block->continue_block != current_block->self)
continue_blocks.insert(current_block->continue_block);
+
+ if (length >= 3)
+ {
+ if (ops[2] & LoopControlUnrollMask)
+ current_block->hint = SPIRBlock::HintUnroll;
+ else if (ops[2] & LoopControlDontUnrollMask)
+ current_block->hint = SPIRBlock::HintDontUnroll;
+ }
break;
}
@@ -3603,303 +3647,449 @@ void Compiler::analyze_parameter_preservation(
}
}
-void Compiler::analyze_variable_scope(SPIRFunction &entry)
+Compiler::AnalyzeVariableScopeAccessHandler::AnalyzeVariableScopeAccessHandler(Compiler &compiler_,
+ SPIRFunction &entry_)
+ : compiler(compiler_)
+ , entry(entry_)
{
- struct AccessHandler : OpcodeHandler
+}
+
+bool Compiler::AnalyzeVariableScopeAccessHandler::follow_function_call(const SPIRFunction &)
+{
+ // Only analyze within this function.
+ return false;
+}
+
+void Compiler::AnalyzeVariableScopeAccessHandler::set_current_block(const SPIRBlock &block)
+{
+ current_block = █
+
+ // If we're branching to a block which uses OpPhi, in GLSL
+ // this will be a variable write when we branch,
+ // so we need to track access to these variables as well to
+ // have a complete picture.
+ const auto test_phi = [this, &block](uint32_t to) {
+ auto &next = compiler.get(to);
+ for (auto &phi : next.phi_variables)
+ {
+ if (phi.parent == block.self)
+ {
+ accessed_variables_to_block[phi.function_variable].insert(block.self);
+ // Phi variables are also accessed in our target branch block.
+ accessed_variables_to_block[phi.function_variable].insert(next.self);
+
+ notify_variable_access(phi.local_variable, block.self);
+ }
+ }
+ };
+
+ switch (block.terminator)
{
- public:
- AccessHandler(Compiler &compiler_, SPIRFunction &entry_)
- : compiler(compiler_)
- , entry(entry_)
- {
- }
+ case SPIRBlock::Direct:
+ notify_variable_access(block.condition, block.self);
+ test_phi(block.next_block);
+ break;
- bool follow_function_call(const SPIRFunction &)
- {
- // Only analyze within this function.
+ case SPIRBlock::Select:
+ notify_variable_access(block.condition, block.self);
+ test_phi(block.true_block);
+ test_phi(block.false_block);
+ break;
+
+ case SPIRBlock::MultiSelect:
+ notify_variable_access(block.condition, block.self);
+ for (auto &target : block.cases)
+ test_phi(target.block);
+ if (block.default_block)
+ test_phi(block.default_block);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Compiler::AnalyzeVariableScopeAccessHandler::notify_variable_access(uint32_t id, uint32_t block)
+{
+ if (id_is_phi_variable(id))
+ accessed_variables_to_block[id].insert(block);
+ else if (id_is_potential_temporary(id))
+ accessed_temporaries_to_block[id].insert(block);
+}
+
+bool Compiler::AnalyzeVariableScopeAccessHandler::id_is_phi_variable(uint32_t id) const
+{
+ if (id >= compiler.get_current_id_bound())
+ return false;
+ auto *var = compiler.maybe_get(id);
+ return var && var->phi_variable;
+}
+
+bool Compiler::AnalyzeVariableScopeAccessHandler::id_is_potential_temporary(uint32_t id) const
+{
+ if (id >= compiler.get_current_id_bound())
+ return false;
+
+ // Temporaries are not created before we start emitting code.
+ return compiler.ids[id].empty() || (compiler.ids[id].get_type() == TypeExpression);
+}
+
+bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint32_t *args, uint32_t length)
+{
+ // Keep track of the types of temporaries, so we can hoist them out as necessary.
+ uint32_t result_type, result_id;
+ if (compiler.instruction_to_result_type(result_type, result_id, op, args, length))
+ result_id_to_type[result_id] = result_type;
+
+ switch (op)
+ {
+ case OpStore:
+ {
+ if (length < 2)
return false;
- }
- void set_current_block(const SPIRBlock &block)
+ uint32_t ptr = args[0];
+ auto *var = compiler.maybe_get_backing_variable(ptr);
+
+ // If we store through an access chain, we have a partial write.
+ if (var)
{
- current_block = █
-
- // If we're branching to a block which uses OpPhi, in GLSL
- // this will be a variable write when we branch,
- // so we need to track access to these variables as well to
- // have a complete picture.
- const auto test_phi = [this, &block](uint32_t to) {
- auto &next = compiler.get(to);
- for (auto &phi : next.phi_variables)
- {
- if (phi.parent == block.self)
- {
- accessed_variables_to_block[phi.function_variable].insert(block.self);
- // Phi variables are also accessed in our target branch block.
- accessed_variables_to_block[phi.function_variable].insert(next.self);
-
- notify_variable_access(phi.local_variable, block.self);
- }
- }
- };
-
- switch (block.terminator)
- {
- case SPIRBlock::Direct:
- notify_variable_access(block.condition, block.self);
- test_phi(block.next_block);
- break;
-
- case SPIRBlock::Select:
- notify_variable_access(block.condition, block.self);
- test_phi(block.true_block);
- test_phi(block.false_block);
- break;
-
- case SPIRBlock::MultiSelect:
- notify_variable_access(block.condition, block.self);
- for (auto &target : block.cases)
- test_phi(target.block);
- if (block.default_block)
- test_phi(block.default_block);
- break;
-
- default:
- break;
- }
+ accessed_variables_to_block[var->self].insert(current_block->self);
+ if (var->self == ptr)
+ complete_write_variables_to_block[var->self].insert(current_block->self);
+ else
+ partial_write_variables_to_block[var->self].insert(current_block->self);
}
- void notify_variable_access(uint32_t id, uint32_t block)
+ // Might try to store a Phi variable here.
+ notify_variable_access(args[1], current_block->self);
+ break;
+ }
+
+ case OpAccessChain:
+ case OpInBoundsAccessChain:
+ {
+ if (length < 3)
+ return false;
+
+ uint32_t ptr = args[2];
+ auto *var = compiler.maybe_get(ptr);
+ if (var)
+ accessed_variables_to_block[var->self].insert(current_block->self);
+
+ for (uint32_t i = 3; i < length; i++)
+ notify_variable_access(args[i], current_block->self);
+
+ // The result of an access chain is a fixed expression and is not really considered a temporary.
+ auto &e = compiler.set(args[1], "", args[0], true);
+ auto *backing_variable = compiler.maybe_get_backing_variable(ptr);
+ e.loaded_from = backing_variable ? backing_variable->self : 0;
+
+ // Other backends might use SPIRAccessChain for this later.
+ compiler.ids[args[1]].set_allow_type_rewrite();
+ break;
+ }
+
+ case OpCopyMemory:
+ {
+ if (length < 2)
+ return false;
+
+ uint32_t lhs = args[0];
+ uint32_t rhs = args[1];
+ auto *var = compiler.maybe_get_backing_variable(lhs);
+
+ // If we store through an access chain, we have a partial write.
+ if (var)
{
- if (id_is_phi_variable(id))
- accessed_variables_to_block[id].insert(block);
- else if (id_is_potential_temporary(id))
- accessed_temporaries_to_block[id].insert(block);
+ accessed_variables_to_block[var->self].insert(current_block->self);
+ if (var->self == lhs)
+ complete_write_variables_to_block[var->self].insert(current_block->self);
+ else
+ partial_write_variables_to_block[var->self].insert(current_block->self);
}
- bool id_is_phi_variable(uint32_t id)
+ var = compiler.maybe_get_backing_variable(rhs);
+ if (var)
+ accessed_variables_to_block[var->self].insert(current_block->self);
+ break;
+ }
+
+ case OpCopyObject:
+ {
+ if (length < 3)
+ return false;
+
+ auto *var = compiler.maybe_get_backing_variable(args[2]);
+ if (var)
+ accessed_variables_to_block[var->self].insert(current_block->self);
+
+ // Might try to copy a Phi variable here.
+ notify_variable_access(args[2], current_block->self);
+ break;
+ }
+
+ case OpLoad:
+ {
+ if (length < 3)
+ return false;
+ uint32_t ptr = args[2];
+ auto *var = compiler.maybe_get_backing_variable(ptr);
+ if (var)
+ accessed_variables_to_block[var->self].insert(current_block->self);
+
+ // Loaded value is a temporary.
+ notify_variable_access(args[1], current_block->self);
+ break;
+ }
+
+ case OpFunctionCall:
+ {
+ if (length < 3)
+ return false;
+
+ length -= 3;
+ args += 3;
+
+ for (uint32_t i = 0; i < length; i++)
{
- if (id >= compiler.get_current_id_bound())
- return false;
- auto *var = compiler.maybe_get(id);
- return var && var->phi_variable;
+ auto *var = compiler.maybe_get_backing_variable(args[i]);
+ if (var)
+ {
+ accessed_variables_to_block[var->self].insert(current_block->self);
+ // Assume we can get partial writes to this variable.
+ partial_write_variables_to_block[var->self].insert(current_block->self);
+ }
+
+ // Cannot easily prove if argument we pass to a function is completely written.
+ // Usually, functions write to a dummy variable,
+ // which is then copied to in full to the real argument.
+
+ // Might try to copy a Phi variable here.
+ notify_variable_access(args[i], current_block->self);
}
- bool id_is_potential_temporary(uint32_t id)
+ // Return value may be a temporary.
+ notify_variable_access(args[1], current_block->self);
+ break;
+ }
+
+ case OpExtInst:
+ {
+ for (uint32_t i = 4; i < length; i++)
+ notify_variable_access(args[i], current_block->self);
+ notify_variable_access(args[1], current_block->self);
+ break;
+ }
+
+ case OpArrayLength:
+ // Uses literals, but cannot be a phi variable, so ignore.
+ break;
+
+ // Atomics shouldn't be able to access function-local variables.
+ // Some GLSL builtins access a pointer.
+
+ case OpCompositeInsert:
+ case OpVectorShuffle:
+ // Specialize for opcode which contains literals.
+ for (uint32_t i = 1; i < 4; i++)
+ notify_variable_access(args[i], current_block->self);
+ break;
+
+ case OpCompositeExtract:
+ // Specialize for opcode which contains literals.
+ for (uint32_t i = 1; i < 3; i++)
+ notify_variable_access(args[i], current_block->self);
+ break;
+
+ default:
+ {
+ // Rather dirty way of figuring out where Phi variables are used.
+ // As long as only IDs are used, we can scan through instructions and try to find any evidence that
+ // the ID of a variable has been used.
+ // There are potential false positives here where a literal is used in-place of an ID,
+ // but worst case, it does not affect the correctness of the compile.
+ // Exhaustive analysis would be better here, but it's not worth it for now.
+ for (uint32_t i = 0; i < length; i++)
+ notify_variable_access(args[i], current_block->self);
+ break;
+ }
+ }
+ return true;
+}
+
+Compiler::StaticExpressionAccessHandler::StaticExpressionAccessHandler(Compiler &compiler_, uint32_t variable_id_)
+ : compiler(compiler_)
+ , variable_id(variable_id_)
+{
+}
+
+bool Compiler::StaticExpressionAccessHandler::follow_function_call(const SPIRFunction &)
+{
+ return false;
+}
+
+bool Compiler::StaticExpressionAccessHandler::handle(spv::Op op, const uint32_t *args, uint32_t length)
+{
+ switch (op)
+ {
+ case OpStore:
+ if (length < 2)
+ return false;
+ if (args[0] == variable_id)
{
- if (id >= compiler.get_current_id_bound())
- return false;
-
- // Temporaries are not created before we start emitting code.
- return compiler.ids[id].empty() || (compiler.ids[id].get_type() == TypeExpression);
+ static_expression = args[1];
+ write_count++;
}
+ break;
- bool handle(spv::Op op, const uint32_t *args, uint32_t length)
+ case OpLoad:
+ if (length < 3)
+ return false;
+ if (args[2] == variable_id && static_expression == 0) // Tried to read from variable before it was initialized.
+ return false;
+ break;
+
+ case OpAccessChain:
+ case OpInBoundsAccessChain:
+ if (length < 3)
+ return false;
+ if (args[2] == variable_id) // If we try to access chain our candidate variable before we store to it, bail.
+ return false;
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariableScopeAccessHandler &handler)
+{
+ auto &cfg = *function_cfgs.find(entry.self)->second;
+
+ // For each variable which is statically accessed.
+ for (auto &accessed_var : handler.accessed_variables_to_block)
+ {
+ auto &blocks = accessed_var.second;
+ auto &var = get(accessed_var.first);
+ auto &type = expression_type(accessed_var.first);
+
+ // Only consider function local variables here.
+ if (var.storage != StorageClassFunction)
+ continue;
+
+ // We cannot be a phi variable.
+ if (var.phi_variable)
+ continue;
+
+ // Only consider arrays here.
+ if (type.array.empty())
+ continue;
+
+ // HACK: Do not consider structs. This is a quirk with how types are currently being emitted.
+ // Structs are emitted after specialization constants and composite constants.
+ // FIXME: Fix declaration order so declared constants can have struct types.
+ if (type.basetype == SPIRType::Struct)
+ continue;
+
+ // If the variable has an initializer, make sure it is a constant expression.
+ uint32_t static_constant_expression = 0;
+ if (var.initializer)
{
- // Keep track of the types of temporaries, so we can hoist them out as necessary.
- uint32_t result_type, result_id;
- if (compiler.instruction_to_result_type(result_type, result_id, op, args, length))
- result_id_to_type[result_id] = result_type;
+ if (ids[var.initializer].get_type() != TypeConstant)
+ continue;
+ static_constant_expression = var.initializer;
- switch (op)
- {
- case OpStore:
- {
- if (length < 2)
- return false;
+ // There can be no stores to this variable, we have now proved we have a LUT.
+ if (handler.complete_write_variables_to_block.count(var.self) != 0 ||
+ handler.partial_write_variables_to_block.count(var.self) != 0)
+ continue;
+ }
+ else
+ {
+ // We can have one, and only one write to the variable, and that write needs to be a constant.
- uint32_t ptr = args[0];
- auto *var = compiler.maybe_get_backing_variable(ptr);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
+ // No partial writes allowed.
+ if (handler.partial_write_variables_to_block.count(var.self) != 0)
+ continue;
- // If we store through an access chain, we have a partial write.
- if (var && var->self == ptr && var->storage == StorageClassFunction)
- complete_write_variables_to_block[var->self].insert(current_block->self);
+ auto itr = handler.complete_write_variables_to_block.find(var.self);
- // Might try to store a Phi variable here.
- notify_variable_access(args[1], current_block->self);
- break;
- }
+ // No writes?
+ if (itr == end(handler.complete_write_variables_to_block))
+ continue;
- case OpAccessChain:
- case OpInBoundsAccessChain:
- {
- if (length < 3)
- return false;
+ // We write to the variable in more than one block.
+ auto &write_blocks = itr->second;
+ if (write_blocks.size() != 1)
+ continue;
- uint32_t ptr = args[2];
- auto *var = compiler.maybe_get(ptr);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
+ // The write needs to happen in the dominating block.
+ DominatorBuilder builder(cfg);
+ for (auto &block : blocks)
+ builder.add_block(block);
+ uint32_t dominator = builder.get_dominator();
- for (uint32_t i = 3; i < length; i++)
- notify_variable_access(args[i], current_block->self);
+ // The complete write happened in a branch or similar, cannot deduce static expression.
+ if (write_blocks.count(dominator) == 0)
+ continue;
- // The result of an access chain is a fixed expression and is not really considered a temporary.
- auto &e = compiler.set(args[1], "", args[0], true);
- auto *backing_variable = compiler.maybe_get_backing_variable(ptr);
- e.loaded_from = backing_variable ? backing_variable->self : 0;
+ // Find the static expression for this variable.
+ StaticExpressionAccessHandler static_expression_handler(*this, var.self);
+ traverse_all_reachable_opcodes(get(dominator), static_expression_handler);
- // Other backends might use SPIRAccessChain for this later.
- compiler.ids[args[1]].set_allow_type_rewrite();
- break;
- }
+ // We want one, and exactly one write
+ if (static_expression_handler.write_count != 1 || static_expression_handler.static_expression == 0)
+ continue;
- case OpCopyMemory:
- {
- if (length < 2)
- return false;
+ // Is it a constant expression?
+ if (ids[static_expression_handler.static_expression].get_type() != TypeConstant)
+ continue;
- uint32_t lhs = args[0];
- uint32_t rhs = args[1];
- auto *var = compiler.maybe_get_backing_variable(lhs);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
-
- // If we store through an access chain, we have a partial write.
- if (var && var->self == lhs)
- complete_write_variables_to_block[var->self].insert(current_block->self);
-
- var = compiler.maybe_get_backing_variable(rhs);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
- break;
- }
-
- case OpCopyObject:
- {
- if (length < 3)
- return false;
-
- auto *var = compiler.maybe_get_backing_variable(args[2]);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
-
- // Might try to copy a Phi variable here.
- notify_variable_access(args[2], current_block->self);
- break;
- }
-
- case OpLoad:
- {
- if (length < 3)
- return false;
- uint32_t ptr = args[2];
- auto *var = compiler.maybe_get_backing_variable(ptr);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
-
- // Loaded value is a temporary.
- notify_variable_access(args[1], current_block->self);
- break;
- }
-
- case OpFunctionCall:
- {
- if (length < 3)
- return false;
-
- length -= 3;
- args += 3;
- for (uint32_t i = 0; i < length; i++)
- {
- auto *var = compiler.maybe_get_backing_variable(args[i]);
- if (var && var->storage == StorageClassFunction)
- accessed_variables_to_block[var->self].insert(current_block->self);
-
- // Cannot easily prove if argument we pass to a function is completely written.
- // Usually, functions write to a dummy variable,
- // which is then copied to in full to the real argument.
-
- // Might try to copy a Phi variable here.
- notify_variable_access(args[i], current_block->self);
- }
-
- // Return value may be a temporary.
- notify_variable_access(args[1], current_block->self);
- break;
- }
-
- case OpExtInst:
- {
- for (uint32_t i = 4; i < length; i++)
- notify_variable_access(args[i], current_block->self);
- notify_variable_access(args[1], current_block->self);
- break;
- }
-
- case OpArrayLength:
- // Uses literals, but cannot be a phi variable, so ignore.
- break;
-
- // Atomics shouldn't be able to access function-local variables.
- // Some GLSL builtins access a pointer.
-
- case OpCompositeInsert:
- case OpVectorShuffle:
- // Specialize for opcode which contains literals.
- for (uint32_t i = 1; i < 4; i++)
- notify_variable_access(args[i], current_block->self);
- break;
-
- case OpCompositeExtract:
- // Specialize for opcode which contains literals.
- for (uint32_t i = 1; i < 3; i++)
- notify_variable_access(args[i], current_block->self);
- break;
-
- default:
- {
- // Rather dirty way of figuring out where Phi variables are used.
- // As long as only IDs are used, we can scan through instructions and try to find any evidence that
- // the ID of a variable has been used.
- // There are potential false positives here where a literal is used in-place of an ID,
- // but worst case, it does not affect the correctness of the compile.
- // Exhaustive analysis would be better here, but it's not worth it for now.
- for (uint32_t i = 0; i < length; i++)
- notify_variable_access(args[i], current_block->self);
- break;
- }
- }
- return true;
+ // We found a LUT!
+ static_constant_expression = static_expression_handler.static_expression;
}
- Compiler &compiler;
- SPIRFunction &entry;
- std::unordered_map> accessed_variables_to_block;
- std::unordered_map> accessed_temporaries_to_block;
- std::unordered_map result_id_to_type;
- std::unordered_map> complete_write_variables_to_block;
- const SPIRBlock *current_block = nullptr;
- } handler(*this, entry);
+ get(static_constant_expression).is_used_as_lut = true;
+ var.static_expression = static_constant_expression;
+ var.statically_assigned = true;
+ var.remapped_variable = true;
+ }
+}
+void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeAccessHandler &handler)
+{
// First, we map out all variable access within a function.
// Essentially a map of block -> { variables accessed in the basic block }
- this->traverse_all_reachable_opcodes(entry, handler);
+ traverse_all_reachable_opcodes(entry, handler);
- // Compute the control flow graph for this function.
- CFG cfg(*this, entry);
+ auto &cfg = *function_cfgs.find(entry.self)->second;
// Analyze if there are parameters which need to be implicitly preserved with an "in" qualifier.
- this->analyze_parameter_preservation(entry, cfg, handler.accessed_variables_to_block,
- handler.complete_write_variables_to_block);
+ analyze_parameter_preservation(entry, cfg, handler.accessed_variables_to_block,
+ handler.complete_write_variables_to_block);
unordered_map potential_loop_variables;
// For each variable which is statically accessed.
for (auto &var : handler.accessed_variables_to_block)
{
+ // Only deal with variables which are considered local variables in this function.
+ if (find(begin(entry.local_variables), end(entry.local_variables), var.first) == end(entry.local_variables))
+ continue;
+
DominatorBuilder builder(cfg);
auto &blocks = var.second;
- auto &type = this->expression_type(var.first);
+ auto &type = expression_type(var.first);
// Figure out which block is dominating all accesses of those variables.
for (auto &block : blocks)
{
// If we're accessing a variable inside a continue block, this variable might be a loop variable.
// We can only use loop variables with scalars, as we cannot track static expressions for vectors.
- if (this->is_continue(block))
+ if (is_continue(block))
{
// Potentially awkward case to check for.
// We might have a variable inside a loop, which is touched by the continue block,
@@ -3907,7 +4097,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// The continue block is dominated by the inner part of the loop, which does not make sense in high-level
// language output because it will be declared before the body,
// so we will have to lift the dominator up to the relevant loop header instead.
- builder.add_block(this->continue_block_to_loop_header[block]);
+ builder.add_block(continue_block_to_loop_header[block]);
// Arrays or structs cannot be loop variables.
if (type.vecsize == 1 && type.columns == 1 && type.basetype != SPIRType::Struct && type.array.empty())
@@ -3934,9 +4124,9 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// will be completely eliminated.
if (dominating_block)
{
- auto &block = this->get(dominating_block);
+ auto &block = get(dominating_block);
block.dominated_variables.push_back(var.first);
- this->get(var.first).dominator = dominating_block;
+ get(var.first).dominator = dominating_block;
}
}
@@ -3962,9 +4152,9 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// If a temporary is used in more than one block, we might have to lift continue block
// access up to loop header like we did for variables.
- if (blocks.size() != 1 && this->is_continue(block))
- builder.add_block(this->continue_block_to_loop_header[block]);
- else if (blocks.size() != 1 && this->is_single_block_loop(block))
+ if (blocks.size() != 1 && is_continue(block))
+ builder.add_block(continue_block_to_loop_header[block]);
+ else if (blocks.size() != 1 && is_single_block_loop(block))
{
// Awkward case, because the loop header is also the continue block.
force_temporary = true;
@@ -3983,10 +4173,10 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// This should be very rare, but if we try to declare a temporary inside a loop,
// and that temporary is used outside the loop as well (spirv-opt inliner likes this)
// we should actually emit the temporary outside the loop.
- this->hoisted_temporaries.insert(var.first);
- this->forced_temporaries.insert(var.first);
+ hoisted_temporaries.insert(var.first);
+ forced_temporaries.insert(var.first);
- auto &block_temporaries = this->get(dominating_block).declare_temporary;
+ auto &block_temporaries = get(dominating_block).declare_temporary;
block_temporaries.emplace_back(handler.result_id_to_type[var.first], var.first);
}
else if (blocks.size() > 1)
@@ -3996,7 +4186,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// In this case, the header is actually inside the for (;;) {} block, and we have problems.
// What we need to do is hoist the temporaries outside the for (;;) {} block in case the header block
// declares the temporary.
- auto &block_temporaries = this->get(dominating_block).potential_declare_temporary;
+ auto &block_temporaries = get(dominating_block).potential_declare_temporary;
block_temporaries.emplace_back(handler.result_id_to_type[var.first], var.first);
}
}
@@ -4007,7 +4197,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// Now, try to analyze whether or not these variables are actually loop variables.
for (auto &loop_variable : potential_loop_variables)
{
- auto &var = this->get(loop_variable.first);
+ auto &var = get(loop_variable.first);
auto dominator = var.dominator;
auto block = loop_variable.second;
@@ -4022,9 +4212,9 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
uint32_t header = 0;
// Find the loop header for this block.
- for (auto b : this->loop_blocks)
+ for (auto b : loop_blocks)
{
- auto &potential_header = this->get(b);
+ auto &potential_header = get(b);
if (potential_header.continue_block == block)
{
header = b;
@@ -4033,7 +4223,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
}
assert(header);
- auto &header_block = this->get(header);
+ auto &header_block = get(header);
auto &blocks = handler.accessed_variables_to_block[loop_variable.first];
// If a loop variable is not used before the loop, it's probably not a loop variable.
@@ -4089,7 +4279,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// Need to sort here as variables come from an unordered container, and pushing stuff in wrong order
// will break reproducability in regression runs.
sort(begin(header_block.loop_variables), end(header_block.loop_variables));
- this->get(loop_variable.first).loop_variable = true;
+ get(loop_variable.first).loop_variable = true;
}
}
@@ -4243,14 +4433,8 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
// Required if we access chain into builtins like gl_GlobalInvocationID.
add_if_builtin(args[2]);
- auto *type = &compiler.get(var->basetype);
-
// Start traversing type hierarchy at the proper non-pointer types.
- while (type->pointer)
- {
- assert(type->parent_type);
- type = &compiler.get(type->parent_type);
- }
+ auto *type = &compiler.get_non_pointer_type(var->basetype);
auto &flags =
type->storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins;
@@ -4329,11 +4513,109 @@ bool Compiler::has_active_builtin(BuiltIn builtin, StorageClass storage)
void Compiler::analyze_image_and_sampler_usage()
{
- CombinedImageSamplerUsageHandler handler(*this);
+ CombinedImageSamplerDrefHandler dref_handler(*this);
+ traverse_all_reachable_opcodes(get(entry_point), dref_handler);
+
+ CombinedImageSamplerUsageHandler handler(*this, dref_handler.dref_combined_samplers);
traverse_all_reachable_opcodes(get(entry_point), handler);
- comparison_samplers = move(handler.comparison_samplers);
- comparison_images = move(handler.comparison_images);
+ comparison_ids = move(handler.comparison_ids);
need_subpass_input = handler.need_subpass_input;
+
+ // Forward information from separate images and samplers into combined image samplers.
+ for (auto &combined : combined_image_samplers)
+ if (comparison_ids.count(combined.sampler_id))
+ comparison_ids.insert(combined.combined_id);
+}
+
+bool Compiler::CombinedImageSamplerDrefHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t)
+{
+ // Mark all sampled images which are used with Dref.
+ switch (opcode)
+ {
+ case OpImageSampleDrefExplicitLod:
+ case OpImageSampleDrefImplicitLod:
+ case OpImageSampleProjDrefExplicitLod:
+ case OpImageSampleProjDrefImplicitLod:
+ case OpImageSparseSampleProjDrefImplicitLod:
+ case OpImageSparseSampleDrefImplicitLod:
+ case OpImageSparseSampleProjDrefExplicitLod:
+ case OpImageSparseSampleDrefExplicitLod:
+ case OpImageDrefGather:
+ case OpImageSparseDrefGather:
+ dref_combined_samplers.insert(args[2]);
+ return true;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Compiler::build_function_control_flow_graphs_and_analyze()
+{
+ CFGBuilder handler(*this);
+ handler.function_cfgs[entry_point].reset(new CFG(*this, get(entry_point)));
+ traverse_all_reachable_opcodes(get(entry_point), handler);
+ function_cfgs = move(handler.function_cfgs);
+
+ for (auto &f : function_cfgs)
+ {
+ auto &func = get(f.first);
+ AnalyzeVariableScopeAccessHandler scope_handler(*this, func);
+ analyze_variable_scope(func, scope_handler);
+ find_function_local_luts(func, scope_handler);
+
+ // Check if we can actually use the loop variables we found in analyze_variable_scope.
+ // To use multiple initializers, we need the same type and qualifiers.
+ for (auto block : func.blocks)
+ {
+ auto &b = get(block);
+ if (b.loop_variables.size() < 2)
+ continue;
+
+ auto &flags = get_decoration_bitset(b.loop_variables.front());
+ uint32_t type = get(b.loop_variables.front()).basetype;
+ bool invalid_initializers = false;
+ for (auto loop_variable : b.loop_variables)
+ {
+ if (flags != get_decoration_bitset(loop_variable) ||
+ type != get(b.loop_variables.front()).basetype)
+ {
+ invalid_initializers = true;
+ break;
+ }
+ }
+
+ if (invalid_initializers)
+ {
+ for (auto loop_variable : b.loop_variables)
+ get(loop_variable).loop_variable = false;
+ b.loop_variables.clear();
+ }
+ }
+ }
+}
+
+Compiler::CFGBuilder::CFGBuilder(spirv_cross::Compiler &compiler_)
+ : compiler(compiler_)
+{
+}
+
+bool Compiler::CFGBuilder::handle(spv::Op, const uint32_t *, uint32_t)
+{
+ return true;
+}
+
+bool Compiler::CFGBuilder::follow_function_call(const SPIRFunction &func)
+{
+ if (function_cfgs.find(func.self) == end(function_cfgs))
+ {
+ function_cfgs[func.self].reset(new CFG(compiler, func));
+ return true;
+ }
+ else
+ return false;
}
bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint32_t *args, uint32_t length)
@@ -4354,20 +4636,12 @@ bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint
return true;
}
-void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_images(uint32_t image)
+void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_ids(uint32_t id)
{
- // Traverse the variable dependency hierarchy and tag everything in its path with comparison images.
- comparison_images.insert(image);
- for (auto &img : dependency_hierarchy[image])
- add_hierarchy_to_comparison_images(img);
-}
-
-void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_samplers(uint32_t sampler)
-{
- // Traverse the variable dependency hierarchy and tag everything in its path with comparison samplers.
- comparison_samplers.insert(sampler);
- for (auto &samp : dependency_hierarchy[sampler])
- add_hierarchy_to_comparison_samplers(samp);
+ // Traverse the variable dependency hierarchy and tag everything in its path with comparison ids.
+ comparison_ids.insert(id);
+ for (auto &dep_id : dependency_hierarchy[id])
+ add_hierarchy_to_comparison_ids(dep_id);
}
bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
@@ -4387,6 +4661,10 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
auto &type = compiler.get(args[0]);
if (type.image.dim == DimSubpassData)
need_subpass_input = true;
+
+ // If we load a SampledImage and it will be used with Dref, propagate the state up.
+ if (dref_combined_samplers.count(args[1]) != 0)
+ add_hierarchy_to_comparison_ids(args[1]);
break;
}
@@ -4396,16 +4674,20 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
return false;
uint32_t result_type = args[0];
+ uint32_t result_id = args[1];
auto &type = compiler.get(result_type);
- if (type.image.depth)
+ if (type.image.depth || dref_combined_samplers.count(result_id) != 0)
{
// This image must be a depth image.
uint32_t image = args[2];
- add_hierarchy_to_comparison_images(image);
+ add_hierarchy_to_comparison_ids(image);
- // This sampler must be a SamplerComparisionState, and not a regular SamplerState.
+ // This sampler must be a SamplerComparisonState, and not a regular SamplerState.
uint32_t sampler = args[3];
- add_hierarchy_to_comparison_samplers(sampler);
+ add_hierarchy_to_comparison_ids(sampler);
+
+ // Mark the OpSampledImage itself as being comparison state.
+ comparison_ids.insert(result_id);
}
return true;
}
@@ -4567,3 +4849,57 @@ bool Compiler::instruction_to_result_type(uint32_t &result_type, uint32_t &resul
return false;
}
}
+
+Bitset Compiler::combined_decoration_for_member(const SPIRType &type, uint32_t index) const
+{
+ Bitset flags;
+ auto &memb = meta[type.self].members;
+ if (index >= memb.size())
+ return flags;
+ auto &dec = memb[index];
+
+ // If our type is a struct, traverse all the members as well recursively.
+ flags.merge_or(dec.decoration_flags);
+ for (uint32_t i = 0; i < type.member_types.size(); i++)
+ flags.merge_or(combined_decoration_for_member(get(type.member_types[i]), i));
+
+ return flags;
+}
+
+bool Compiler::is_desktop_only_format(spv::ImageFormat format)
+{
+ switch (format)
+ {
+ // Desktop-only formats
+ case ImageFormatR11fG11fB10f:
+ case ImageFormatR16f:
+ case ImageFormatRgb10A2:
+ case ImageFormatR8:
+ case ImageFormatRg8:
+ case ImageFormatR16:
+ case ImageFormatRg16:
+ case ImageFormatRgba16:
+ case ImageFormatR16Snorm:
+ case ImageFormatRg16Snorm:
+ case ImageFormatRgba16Snorm:
+ case ImageFormatR8Snorm:
+ case ImageFormatRg8Snorm:
+ case ImageFormatR8ui:
+ case ImageFormatRg8ui:
+ case ImageFormatR16ui:
+ case ImageFormatRgb10a2ui:
+ case ImageFormatR8i:
+ case ImageFormatRg8i:
+ case ImageFormatR16i:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool Compiler::image_is_comparison(const spirv_cross::SPIRType &type, uint32_t id) const
+{
+ return type.image.depth || (comparison_ids.count(id) != 0);
+}
diff --git a/deps/SPIRV-Cross/spirv_cross.hpp b/deps/SPIRV-Cross/spirv_cross.hpp
index 12dcae34e9..159e1988be 100644
--- a/deps/SPIRV-Cross/spirv_cross.hpp
+++ b/deps/SPIRV-Cross/spirv_cross.hpp
@@ -18,11 +18,11 @@
#define SPIRV_CROSS_HPP
#include "spirv.hpp"
+#include "spirv_cfg.hpp"
#include "spirv_common.hpp"
namespace spirv_cross
{
-class CFG;
struct Resource
{
// Resources are identified with their SPIR-V ID.
@@ -170,6 +170,15 @@ public:
// Gets the SPIR-V type of a variable.
const SPIRType &get_type_from_variable(uint32_t id) const;
+ // Gets the id of SPIR-V type underlying the given type_id, which might be a pointer.
+ uint32_t get_non_pointer_type_id(uint32_t type_id) const;
+
+ // Gets the SPIR-V type underlying the given type, which might be a pointer.
+ const SPIRType &get_non_pointer_type(const SPIRType &type) const;
+
+ // Gets the SPIR-V type underlying the given type_id, which might be a pointer.
+ const SPIRType &get_non_pointer_type(uint32_t type_id) const;
+
// Gets the underlying storage class for an OpVariable.
spv::StorageClass get_storage_class(uint32_t id) const;
@@ -667,8 +676,6 @@ protected:
variable_remap_callback(type, var_name, type_name);
}
- void analyze_variable_scope(SPIRFunction &function);
-
void parse();
void parse(const Instruction &i);
@@ -817,8 +824,7 @@ protected:
// There might be unrelated IDs found in this set which do not correspond to actual variables.
// This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs.
// Similar is implemented for images, as well as if subpass inputs are needed.
- std::unordered_set comparison_samplers;
- std::unordered_set comparison_images;
+ std::unordered_set comparison_ids;
bool need_subpass_input = false;
// In certain backends, we will need to use a dummy sampler to be able to emit code.
@@ -827,26 +833,89 @@ protected:
uint32_t dummy_sampler_id = 0;
void analyze_image_and_sampler_usage();
+
+ struct CombinedImageSamplerDrefHandler : OpcodeHandler
+ {
+ CombinedImageSamplerDrefHandler(Compiler &compiler_)
+ : compiler(compiler_)
+ {
+ }
+ bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
+
+ Compiler &compiler;
+ std::unordered_set dref_combined_samplers;
+ };
+
struct CombinedImageSamplerUsageHandler : OpcodeHandler
{
- CombinedImageSamplerUsageHandler(Compiler &compiler_)
+ CombinedImageSamplerUsageHandler(Compiler &compiler_,
+ const std::unordered_set &dref_combined_samplers_)
: compiler(compiler_)
+ , dref_combined_samplers(dref_combined_samplers_)
{
}
bool begin_function_scope(const uint32_t *args, uint32_t length) override;
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
+ const std::unordered_set &dref_combined_samplers;
std::unordered_map> dependency_hierarchy;
- std::unordered_set comparison_images;
- std::unordered_set comparison_samplers;
+ std::unordered_set comparison_ids;
- void add_hierarchy_to_comparison_samplers(uint32_t sampler);
- void add_hierarchy_to_comparison_images(uint32_t sampler);
+ void add_hierarchy_to_comparison_ids(uint32_t ids);
bool need_subpass_input = false;
};
+ void build_function_control_flow_graphs_and_analyze();
+ std::unordered_map> function_cfgs;
+ struct CFGBuilder : OpcodeHandler
+ {
+ CFGBuilder(Compiler &compiler_);
+
+ bool follow_function_call(const SPIRFunction &func) override;
+ bool handle(spv::Op op, const uint32_t *args, uint32_t length) override;
+ Compiler &compiler;
+ std::unordered_map> function_cfgs;
+ };
+
+ struct AnalyzeVariableScopeAccessHandler : OpcodeHandler
+ {
+ AnalyzeVariableScopeAccessHandler(Compiler &compiler_, SPIRFunction &entry_);
+
+ bool follow_function_call(const SPIRFunction &) override;
+ void set_current_block(const SPIRBlock &block) override;
+
+ void notify_variable_access(uint32_t id, uint32_t block);
+ bool id_is_phi_variable(uint32_t id) const;
+ bool id_is_potential_temporary(uint32_t id) const;
+ bool handle(spv::Op op, const uint32_t *args, uint32_t length) override;
+
+ Compiler &compiler;
+ SPIRFunction &entry;
+ std::unordered_map> accessed_variables_to_block;
+ std::unordered_map> accessed_temporaries_to_block;
+ std::unordered_map result_id_to_type;
+ std::unordered_map> complete_write_variables_to_block;
+ std::unordered_map> partial_write_variables_to_block;
+ const SPIRBlock *current_block = nullptr;
+ };
+
+ struct StaticExpressionAccessHandler : OpcodeHandler
+ {
+ StaticExpressionAccessHandler(Compiler &compiler_, uint32_t variable_id_);
+ bool follow_function_call(const SPIRFunction &) override;
+ bool handle(spv::Op op, const uint32_t *args, uint32_t length) override;
+
+ Compiler &compiler;
+ uint32_t variable_id;
+ uint32_t static_expression = 0;
+ uint32_t write_count = 0;
+ };
+
+ void analyze_variable_scope(SPIRFunction &function, AnalyzeVariableScopeAccessHandler &handler);
+ void find_function_local_luts(SPIRFunction &function, const AnalyzeVariableScopeAccessHandler &handler);
+
void make_constant_null(uint32_t id, uint32_t type);
std::vector declared_capabilities;
@@ -856,6 +925,11 @@ protected:
bool instruction_to_result_type(uint32_t &result_type, uint32_t &result_id, spv::Op op, const uint32_t *args,
uint32_t length);
+ Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index) const;
+ static bool is_desktop_only_format(spv::ImageFormat format);
+
+ bool image_is_comparison(const SPIRType &type, uint32_t id) const;
+
private:
// Used only to implement the old deprecated get_entry_point() interface.
const SPIREntryPoint &get_first_entry_point(const std::string &name) const;
diff --git a/deps/SPIRV-Cross/spirv_glsl.cpp b/deps/SPIRV-Cross/spirv_glsl.cpp
index bc8fddd243..a973274616 100644
--- a/deps/SPIRV-Cross/spirv_glsl.cpp
+++ b/deps/SPIRV-Cross/spirv_glsl.cpp
@@ -418,6 +418,7 @@ string CompilerGLSL::compile()
backend.supports_extensions = true;
// Scan the SPIR-V to find trivial uses of extensions.
+ build_function_control_flow_graphs_and_analyze();
find_static_extensions();
fixup_image_load_store_access();
update_active_builtins();
@@ -689,22 +690,6 @@ void CompilerGLSL::emit_struct(SPIRType &type)
statement("");
}
-Bitset CompilerGLSL::combined_decoration_for_member(const SPIRType &type, uint32_t index)
-{
- Bitset flags;
- auto &memb = meta[type.self].members;
- if (index >= memb.size())
- return flags;
- auto &dec = memb[index];
-
- // If our type is a struct, traverse all the members as well recursively.
- flags.merge_or(dec.decoration_flags);
- for (uint32_t i = 0; i < type.member_types.size(); i++)
- flags.merge_or(combined_decoration_for_member(get(type.member_types[i]), i));
-
- return flags;
-}
-
string CompilerGLSL::to_interpolation_qualifiers(const Bitset &flags)
{
string res;
@@ -786,10 +771,8 @@ string CompilerGLSL::layout_for_member(const SPIRType &type, uint32_t index)
const char *CompilerGLSL::format_to_glsl(spv::ImageFormat format)
{
- auto check_desktop = [this] {
- if (options.es)
- SPIRV_CROSS_THROW("Attempting to use image format not supported in ES profile.");
- };
+ if (options.es && is_desktop_only_format(format))
+ SPIRV_CROSS_THROW("Attempting to use image format not supported in ES profile.");
switch (format)
{
@@ -807,7 +790,6 @@ const char *CompilerGLSL::format_to_glsl(spv::ImageFormat format)
return "rg32f";
case ImageFormatRg16f:
return "rg16f";
-
case ImageFormatRgba32i:
return "rgba32i";
case ImageFormatRgba16i:
@@ -820,7 +802,6 @@ const char *CompilerGLSL::format_to_glsl(spv::ImageFormat format)
return "rg32i";
case ImageFormatRg16i:
return "rg16i";
-
case ImageFormatRgba32ui:
return "rgba32ui";
case ImageFormatRgba16ui:
@@ -833,71 +814,46 @@ const char *CompilerGLSL::format_to_glsl(spv::ImageFormat format)
return "rg32ui";
case ImageFormatRg16ui:
return "rg16ui";
-
- // Desktop-only formats
case ImageFormatR11fG11fB10f:
- check_desktop();
return "r11f_g11f_b10f";
case ImageFormatR16f:
- check_desktop();
return "r16f";
case ImageFormatRgb10A2:
- check_desktop();
return "rgb10_a2";
case ImageFormatR8:
- check_desktop();
return "r8";
case ImageFormatRg8:
- check_desktop();
return "rg8";
case ImageFormatR16:
- check_desktop();
return "r16";
case ImageFormatRg16:
- check_desktop();
return "rg16";
case ImageFormatRgba16:
- check_desktop();
return "rgba16";
case ImageFormatR16Snorm:
- check_desktop();
return "r16_snorm";
case ImageFormatRg16Snorm:
- check_desktop();
return "rg16_snorm";
case ImageFormatRgba16Snorm:
- check_desktop();
return "rgba16_snorm";
case ImageFormatR8Snorm:
- check_desktop();
return "r8_snorm";
case ImageFormatRg8Snorm:
- check_desktop();
return "rg8_snorm";
-
case ImageFormatR8ui:
- check_desktop();
return "r8ui";
case ImageFormatRg8ui:
- check_desktop();
return "rg8ui";
case ImageFormatR16ui:
- check_desktop();
return "r16ui";
case ImageFormatRgb10a2ui:
- check_desktop();
return "rgb10_a2ui";
-
case ImageFormatR8i:
- check_desktop();
return "r8i";
case ImageFormatRg8i:
- check_desktop();
return "rg8i";
case ImageFormatR16i:
- check_desktop();
return "r16i";
-
default:
case ImageFormatUnknown:
return nullptr;
@@ -1695,7 +1651,7 @@ void CompilerGLSL::emit_specialization_constant_op(const SPIRConstantOp &constan
statement("const ", variable_decl(type, name), " = ", constant_op_expression(constant), ";");
}
-void CompilerGLSL::emit_specialization_constant(const SPIRConstant &constant)
+void CompilerGLSL::emit_constant(const SPIRConstant &constant)
{
auto &type = get(constant.constant_type);
auto name = to_name(constant.self);
@@ -2116,25 +2072,25 @@ void CompilerGLSL::emit_resources()
//
// TODO: If we have the fringe case that we create a spec constant which depends on a struct type,
// we'll have to deal with that, but there's currently no known way to express that.
- if (options.vulkan_semantics)
+ for (auto &id : ids)
{
- for (auto &id : ids)
+ if (id.get_type() == TypeConstant)
{
- if (id.get_type() == TypeConstant)
- {
- auto &c = id.get();
- if (!c.specialization)
- continue;
+ auto &c = id.get();
- emit_specialization_constant(c);
- emitted = true;
- }
- else if (id.get_type() == TypeConstantOp)
+ bool needs_declaration = (c.specialization && options.vulkan_semantics) || c.is_used_as_lut;
+
+ if (needs_declaration)
{
- emit_specialization_constant_op(id.get());
+ emit_constant(c);
emitted = true;
}
}
+ else if (options.vulkan_semantics && id.get_type() == TypeConstantOp)
+ {
+ emit_specialization_constant_op(id.get());
+ emitted = true;
+ }
}
if (emitted)
@@ -2246,7 +2202,8 @@ void CompilerGLSL::emit_resources()
{
// For gl_InstanceIndex emulation on GLES, the API user needs to
// supply this uniform.
- if (meta[var.self].decoration.builtin_type == BuiltInInstanceIndex && !options.vulkan_semantics)
+ if (options.vertex.support_nonzero_base_instance &&
+ meta[var.self].decoration.builtin_type == BuiltInInstanceIndex && !options.vulkan_semantics)
{
statement("uniform int SPIRV_Cross_BaseInstance;");
emitted = true;
@@ -2342,9 +2299,9 @@ string CompilerGLSL::enclose_expression(const string &expr)
uint32_t paren_count = 0;
for (auto c : expr)
{
- if (c == '(')
+ if (c == '(' || c == '[')
paren_count++;
- else if (c == ')')
+ else if (c == ')' || c == ']')
{
assert(paren_count);
paren_count--;
@@ -2468,6 +2425,8 @@ string CompilerGLSL::to_expression(uint32_t id)
return builtin_to_glsl(dec.builtin_type, StorageClassGeneric);
else if (c.specialization && options.vulkan_semantics)
return to_name(id);
+ else if (c.is_used_as_lut)
+ return to_name(id);
else if (type.basetype == SPIRType::Struct && !backend.can_declare_struct_inline)
return to_name(id);
else if (!type.array.empty() && !backend.can_declare_arrays_inline)
@@ -2545,15 +2504,15 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop)
break;
#define GLSL_BOP(opname, x) \
- case Op##opname: \
- binary = true; \
- op = x; \
+ case Op##opname: \
+ binary = true; \
+ op = x; \
break
#define GLSL_UOP(opname, x) \
- case Op##opname: \
- unary = true; \
- op = x; \
+ case Op##opname: \
+ unary = true; \
+ op = x; \
break
GLSL_UOP(SNegate, "-");
@@ -2597,11 +2556,14 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop)
// In order to preserve its compile-time constness in Vulkan GLSL,
// we need to reduce the OpSelect expression back to this simplified model.
// If we cannot, fail.
- if (!to_trivial_mix_op(type, op, cop.arguments[2], cop.arguments[1], cop.arguments[0]))
+ if (to_trivial_mix_op(type, op, cop.arguments[2], cop.arguments[1], cop.arguments[0]))
{
- SPIRV_CROSS_THROW(
- "Cannot implement specialization constant op OpSelect. "
- "Need trivial select implementation which can be resolved to a simple cast from boolean.");
+ // Implement as a simple cast down below.
+ }
+ else
+ {
+ // Implement a ternary and pray the compiler understands it :)
+ return to_ternary_expression(type, cop.arguments[0], cop.arguments[1], cop.arguments[2]);
}
break;
}
@@ -3501,7 +3463,7 @@ bool CompilerGLSL::check_explicit_lod_allowed(uint32_t lod)
return allowed;
}
-string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod)
+string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t tex)
{
const char *type;
switch (imgtype.image.dim)
@@ -3531,7 +3493,7 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
bool use_explicit_lod = check_explicit_lod_allowed(lod);
- if (op == "textureLod" || op == "textureProjLod" || op == "textureGrad")
+ if (op == "textureLod" || op == "textureProjLod" || op == "textureGrad" || op == "textureProjGrad")
{
if (is_legacy_es())
{
@@ -3542,25 +3504,64 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
require_extension_internal("GL_ARB_shader_texture_lod");
}
+ if (op == "textureLodOffset" || op == "textureProjLodOffset")
+ {
+ if (is_legacy_es())
+ SPIRV_CROSS_THROW(join(op, " not allowed in legacy ES"));
+
+ require_extension_internal("GL_EXT_gpu_shader4");
+ }
+
+ // GLES has very limited support for shadow samplers.
+ // Basically shadow2D and shadow2DProj work through EXT_shadow_samplers,
+ // everything else can just throw
+ if (image_is_comparison(imgtype, tex) && is_legacy_es())
+ {
+ if (op == "texture" || op == "textureProj")
+ require_extension_internal("GL_EXT_shadow_samplers");
+ else
+ SPIRV_CROSS_THROW(join(op, " not allowed on depth samplers in legacy ES"));
+ }
+
+ bool is_es_and_depth = is_legacy_es() && image_is_comparison(imgtype, tex);
+ std::string type_prefix = image_is_comparison(imgtype, tex) ? "shadow" : "texture";
+
if (op == "texture")
- return join("texture", type);
+ return is_es_and_depth ? join(type_prefix, type, "EXT") : join(type_prefix, type);
else if (op == "textureLod")
{
if (use_explicit_lod)
- return join("texture", type, is_legacy_es() ? "LodEXT" : "Lod");
+ return join(type_prefix, type, is_legacy_es() ? "LodEXT" : "Lod");
else
- return join("texture", type);
+ return join(type_prefix, type);
}
else if (op == "textureProj")
- return join("texture", type, "Proj");
+ return join(type_prefix, type, is_es_and_depth ? "ProjEXT" : "Proj");
else if (op == "textureGrad")
- return join("texture", type, is_legacy_es() ? "GradEXT" : is_legacy_desktop() ? "GradARB" : "Grad");
+ return join(type_prefix, type, is_legacy_es() ? "GradEXT" : is_legacy_desktop() ? "GradARB" : "Grad");
else if (op == "textureProjLod")
{
if (use_explicit_lod)
- return join("texture", type, is_legacy_es() ? "ProjLodEXT" : "ProjLod");
+ return join(type_prefix, type, is_legacy_es() ? "ProjLodEXT" : "ProjLod");
else
- return join("texture", type);
+ return join(type_prefix, type, "Proj");
+ }
+ else if (op == "textureLodOffset")
+ {
+ if (use_explicit_lod)
+ return join(type_prefix, type, "LodOffset");
+ else
+ return join(type_prefix, type);
+ }
+ else if (op == "textureProjGrad")
+ return join(type_prefix, type,
+ is_legacy_es() ? "ProjGradEXT" : is_legacy_desktop() ? "ProjGradARB" : "ProjGrad");
+ else if (op == "textureProjLodOffset")
+ {
+ if (use_explicit_lod)
+ return join(type_prefix, type, "ProjLodOffset");
+ else
+ return join(type_prefix, type, "ProjOffset");
}
else
{
@@ -3622,6 +3623,37 @@ bool CompilerGLSL::to_trivial_mix_op(const SPIRType &type, string &op, uint32_t
return ret;
}
+string CompilerGLSL::to_ternary_expression(const SPIRType &restype, uint32_t select, uint32_t true_value,
+ uint32_t false_value)
+{
+ string expr;
+ auto &lerptype = expression_type(select);
+
+ if (lerptype.vecsize == 1)
+ expr = join(to_enclosed_expression(select), " ? ", to_enclosed_expression(true_value), " : ",
+ to_enclosed_expression(false_value));
+ else
+ {
+ auto swiz = [this](uint32_t expression, uint32_t i) { return to_extract_component_expression(expression, i); };
+
+ expr = type_to_glsl_constructor(restype);
+ expr += "(";
+ for (uint32_t i = 0; i < restype.vecsize; i++)
+ {
+ expr += swiz(select, i);
+ expr += " ? ";
+ expr += swiz(true_value, i);
+ expr += " : ";
+ expr += swiz(false_value, i);
+ if (i + 1 < restype.vecsize)
+ expr += ", ";
+ }
+ expr += ")";
+ }
+
+ return expr;
+}
+
void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp)
{
auto &lerptype = expression_type(lerp);
@@ -3652,31 +3684,7 @@ void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left,
// Could use GL_EXT_shader_integer_mix on desktop at least,
// but Apple doesn't support it. :(
// Just implement it as ternary expressions.
- string expr;
- if (lerptype.vecsize == 1)
- expr = join(to_enclosed_expression(lerp), " ? ", to_enclosed_expression(right), " : ",
- to_enclosed_expression(left));
- else
- {
- auto swiz = [this](uint32_t expression, uint32_t i) {
- return to_extract_component_expression(expression, i);
- };
-
- expr = type_to_glsl_constructor(restype);
- expr += "(";
- for (uint32_t i = 0; i < restype.vecsize; i++)
- {
- expr += swiz(lerp, i);
- expr += " ? ";
- expr += swiz(right, i);
- expr += " : ";
- expr += swiz(left, i);
- if (i + 1 < restype.vecsize)
- expr += ", ";
- }
- expr += ")";
- }
-
+ auto expr = to_ternary_expression(get(result_type), lerp, right, left);
emit_op(result_type, id, expr, should_forward(left) && should_forward(right) && should_forward(lerp));
inherit_expression_dependencies(id, left);
inherit_expression_dependencies(id, right);
@@ -3759,7 +3767,7 @@ void CompilerGLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_i
if (options.vulkan_semantics && combined_image_samplers.empty())
{
emit_binary_func_op(result_type, result_id, image_id, samp_id,
- type_to_glsl(get(result_type)).c_str());
+ type_to_glsl(get(result_type), result_id).c_str());
// Make sure to suppress usage tracking. It is illegal to create temporaries of opaque types.
forwarded_temporaries.erase(result_id);
@@ -3924,6 +3932,10 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
coffset, offset, bias, comp, sample, &forward);
expr += ")";
+ // texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here.
+ if (is_legacy() && image_is_comparison(imgtype, img))
+ expr += ".r";
+
emit_op(result_type, id, expr, forward);
for (auto &inherit : inherited_expressions)
inherit_expression_dependencies(id, inherit);
@@ -3944,8 +3956,9 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
// Returns the function name for a texture sampling function for the specified image and sampling characteristics.
// For some subclasses, the function is a method on the specified image.
-string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
- bool has_array_offsets, bool has_offset, bool has_grad, bool, uint32_t lod)
+string CompilerGLSL::to_function_name(uint32_t tex, const SPIRType &imgtype, bool is_fetch, bool is_gather,
+ bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool,
+ uint32_t lod)
{
string fname;
@@ -3955,7 +3968,7 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad = false;
if (((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
- imgtype.image.depth && lod)
+ image_is_comparison(imgtype, tex) && lod)
{
auto *constant_lod = maybe_get(lod);
if (!constant_lod || constant_lod->scalar_f32() != 0.0f)
@@ -3985,7 +3998,7 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
if (has_offset)
fname += "Offset";
- return is_legacy() ? legacy_tex_op(fname, imgtype, lod) : fname;
+ return is_legacy() ? legacy_tex_op(fname, imgtype, lod, tex) : fname;
}
std::string CompilerGLSL::convert_separate_image_to_combined(uint32_t id)
@@ -4070,7 +4083,7 @@ string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, boo
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad =
((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
- imgtype.image.depth && lod;
+ image_is_comparison(imgtype, img) && lod;
if (dref)
{
@@ -4484,6 +4497,16 @@ void CompilerGLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
emit_binary_func_op(result_type, id, args[0], args[1], "interpolateAtOffset");
break;
+ case GLSLstd450NMin:
+ emit_binary_func_op(result_type, id, args[0], args[1], "unsupported_glsl450_nmin");
+ break;
+ case GLSLstd450NMax:
+ emit_binary_func_op(result_type, id, args[0], args[1], "unsupported_glsl450_nmax");
+ break;
+ case GLSLstd450NClamp:
+ emit_binary_func_op(result_type, id, args[0], args[1], "unsupported_glsl450_nclamp");
+ break;
+
default:
statement("// unimplemented GLSL op ", eop);
break;
@@ -4802,7 +4825,7 @@ void CompilerGLSL::emit_subgroup_op(const Instruction &i)
break;
// clang-format off
-#define GROUP_OP(op, glsl_op) \
+#define GLSL_GROUP_OP(op, glsl_op) \
case OpGroupNonUniform##op: \
{ \
auto operation = static_cast(ops[3]); \
@@ -4818,20 +4841,20 @@ case OpGroupNonUniform##op: \
SPIRV_CROSS_THROW("Invalid group operation."); \
break; \
}
- GROUP_OP(FAdd, Add)
- GROUP_OP(FMul, Mul)
- GROUP_OP(FMin, Min)
- GROUP_OP(FMax, Max)
- GROUP_OP(IAdd, Add)
- GROUP_OP(IMul, Mul)
- GROUP_OP(SMin, Min)
- GROUP_OP(SMax, Max)
- GROUP_OP(UMin, Min)
- GROUP_OP(UMax, Max)
- GROUP_OP(BitwiseAnd, And)
- GROUP_OP(BitwiseOr, Or)
- GROUP_OP(BitwiseXor, Xor)
-#undef GROUP_OP
+ 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(BitwiseAnd, And)
+ GLSL_GROUP_OP(BitwiseOr, Or)
+ GLSL_GROUP_OP(BitwiseXor, Xor)
+#undef GLSL_GROUP_OP
// clang-format on
case OpGroupNonUniformQuadSwap:
@@ -4961,10 +4984,15 @@ string CompilerGLSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
case BuiltInInstanceIndex:
if (options.vulkan_semantics)
return "gl_InstanceIndex";
- else
+ else if (options.vertex.support_nonzero_base_instance)
return "(gl_InstanceID + SPIRV_Cross_BaseInstance)"; // ... but not gl_InstanceID.
+ else
+ return "gl_InstanceID";
case BuiltInPrimitiveId:
- return "gl_PrimitiveID";
+ if (storage == StorageClassInput && get_entry_point().model == ExecutionModelGeometry)
+ return "gl_PrimitiveIDIn";
+ else
+ return "gl_PrimitiveID";
case BuiltInInvocationId:
return "gl_InvocationID";
case BuiltInLayer:
@@ -5119,16 +5147,10 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
if (!chain_only)
expr = to_enclosed_expression(base);
- uint32_t type_id = expression_type_id(base);
- const auto *type = &get(type_id);
-
// Start traversing type hierarchy at the proper non-pointer types,
// but keep type_id referencing the original pointer for use below.
- while (type->pointer)
- {
- assert(type->parent_type);
- type = &get(type->parent_type);
- }
+ uint32_t type_id = expression_type_id(base);
+ const auto *type = &get_non_pointer_type(type_id);
bool access_chain_is_arrayed = expr.find_first_of('[') != string::npos;
bool row_major_matrix_needs_conversion = is_non_native_row_major_matrix(base);
@@ -5571,14 +5593,8 @@ std::pair CompilerGLSL::flattened_access_chain_offset(con
bool *need_transpose,
uint32_t *out_matrix_stride)
{
- const auto *type = &basetype;
-
// Start traversing type hierarchy at the proper non-pointer types.
- while (type->pointer)
- {
- assert(type->parent_type);
- type = &get(type->parent_type);
- }
+ const auto *type = &get_non_pointer_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.
@@ -6085,10 +6101,10 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
#define GLSL_BOP_CAST(op, type) \
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, glsl_opcode_is_sign_invariant(opcode))
#define GLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
-#define QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
+#define GLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define GLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define GLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
-#define GLSL_GLSL_BFOP_CAST(op, type) \
+#define GLSL_BFOP_CAST(op, type) \
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, glsl_opcode_is_sign_invariant(opcode))
#define GLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define GLSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
@@ -6125,6 +6141,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
auto expr = to_expression(ptr);
+ // We might need to bitcast in order to load from a builtin.
+ bitcast_from_builtin_load(ptr, expr, get(result_type));
+
if (ptr_expression)
ptr_expression->need_transpose = old_need_transpose;
@@ -6174,6 +6193,10 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
var->static_expression = ops[1];
else if (var && var->loop_variable && !var->loop_variable_enable)
var->static_expression = ops[1];
+ else if (var && var->remapped_variable)
+ {
+ // Skip the write.
+ }
else if (var && flattened_structs.count(ops[0]))
{
store_flattened_struct(*var, ops[1]);
@@ -6182,11 +6205,15 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
else
{
auto rhs = to_expression(ops[1]);
+
// Statements to OpStore may be empty if it is a struct with zero members. Just forward the store to /dev/null.
if (!rhs.empty())
{
auto lhs = to_expression(ops[0]);
+ // We might need to bitcast in order to store to a builtin.
+ bitcast_to_builtin_store(ops[0], rhs, expression_type(ops[1]));
+
// Tries to optimize assignments like " = op expr".
// While this is purely cosmetic, this is important for legacy ESSL where loop
// variable increments must be in either i++ or i += const-expr.
@@ -6852,7 +6879,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
case OpIEqual:
{
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(equal, SPIRType::Int);
+ GLSL_BFOP_CAST(equal, SPIRType::Int);
else
GLSL_BOP_CAST(==, SPIRType::Int);
break;
@@ -6871,7 +6898,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
case OpINotEqual:
{
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(notEqual, SPIRType::Int);
+ GLSL_BFOP_CAST(notEqual, SPIRType::Int);
else
GLSL_BOP_CAST(!=, SPIRType::Int);
break;
@@ -6892,7 +6919,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
auto type = opcode == OpUGreaterThan ? SPIRType::UInt : SPIRType::Int;
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(greaterThan, type);
+ GLSL_BFOP_CAST(greaterThan, type);
else
GLSL_BOP_CAST(>, type);
break;
@@ -6912,7 +6939,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
auto type = opcode == OpUGreaterThanEqual ? SPIRType::UInt : SPIRType::Int;
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(greaterThanEqual, type);
+ GLSL_BFOP_CAST(greaterThanEqual, type);
else
GLSL_BOP_CAST(>=, type);
break;
@@ -6932,7 +6959,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
auto type = opcode == OpULessThan ? SPIRType::UInt : SPIRType::Int;
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(lessThan, type);
+ GLSL_BFOP_CAST(lessThan, type);
else
GLSL_BOP_CAST(<, type);
break;
@@ -6952,7 +6979,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
auto type = opcode == OpULessThanEqual ? SPIRType::UInt : SPIRType::Int;
if (expression_type(ops[2]).vecsize > 1)
- GLSL_GLSL_BFOP_CAST(lessThanEqual, type);
+ GLSL_BFOP_CAST(lessThanEqual, type);
else
GLSL_BOP_CAST(<=, type);
break;
@@ -7126,7 +7153,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
// Bitfield
case OpBitFieldInsert:
// TODO: The signedness of inputs is strict in GLSL, but not in SPIR-V, bitcast if necessary.
- QFOP(bitfieldInsert);
+ GLSL_QFOP(bitfieldInsert);
break;
case OpBitFieldSExtract:
@@ -7987,6 +8014,30 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
emit_subgroup_op(instruction);
break;
+ case OpFUnordEqual:
+ GLSL_BFOP(unsupported_FUnordEqual);
+ break;
+
+ case OpFUnordNotEqual:
+ GLSL_BFOP(unsupported_FUnordNotEqual);
+ break;
+
+ case OpFUnordLessThan:
+ GLSL_BFOP(unsupported_FUnordLessThan);
+ break;
+
+ case OpFUnordGreaterThan:
+ GLSL_BFOP(unsupported_FUnordGreaterThan);
+ break;
+
+ case OpFUnordLessThanEqual:
+ GLSL_BFOP(unsupported_FUnordLessThanEqual);
+ break;
+
+ case OpFUnordGreaterThanEqual:
+ GLSL_BFOP(unsupported_FUnordGreaterThanEqual);
+ break;
+
default:
statement("// unimplemented op ", instruction.op);
break;
@@ -8245,6 +8296,11 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
return join(direction, to_qualifiers_glsl(arg.id), variable_decl(type, to_name(arg.id), arg.id));
}
+string CompilerGLSL::to_initializer_expression(const SPIRVariable &var)
+{
+ return to_expression(var.initializer);
+}
+
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
{
// Ignore the pointer type since GLSL doesn't have pointers.
@@ -8262,7 +8318,7 @@ string CompilerGLSL::variable_decl(const SPIRVariable &variable)
{
uint32_t expr = variable.initializer;
if (ids[expr].get_type() != TypeUndef)
- res += join(" = ", to_expression(variable.initializer));
+ res += join(" = ", to_initializer_expression(variable));
}
return res;
}
@@ -8375,7 +8431,7 @@ string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
}
}
-string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t /* id */)
+string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id)
{
auto &imagetype = get(type.image.type);
string res;
@@ -8448,8 +8504,11 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t /* id */)
}
// "Shadow" state in GLSL only exists for samplers and combined image samplers.
- if (((type.basetype == SPIRType::SampledImage) || (type.basetype == SPIRType::Sampler)) && type.image.depth)
+ if (((type.basetype == SPIRType::SampledImage) || (type.basetype == SPIRType::Sampler)) &&
+ image_is_comparison(type, id))
+ {
res += "Shadow";
+ }
return res;
}
@@ -8495,7 +8554,7 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::Sampler:
// The depth field is set by calling code based on the variable ID of the sampler, effectively reintroducing
// this distinction into the type system.
- return comparison_samplers.count(id) ? "samplerShadow" : "sampler";
+ return comparison_ids.count(id) ? "samplerShadow" : "sampler";
case SPIRType::Void:
return "void";
@@ -8713,13 +8772,8 @@ void CompilerGLSL::add_function_overload(const SPIRFunction &func)
// Parameters can vary with pointer type or not,
// but that will not change the signature in GLSL/HLSL,
// so strip the pointer type before hashing.
- uint32_t type_id = arg.type;
- auto *type = &get(type_id);
- while (type->pointer)
- {
- type_id = type->parent_type;
- type = &get(type_id);
- }
+ uint32_t type_id = get_non_pointer_type_id(arg.type);
+ auto &type = get(type_id);
if (!combined_image_samplers.empty())
{
@@ -8727,8 +8781,8 @@ void CompilerGLSL::add_function_overload(const SPIRFunction &func)
// we pass down to callees, because they may be shuffled around.
// Ignore these arguments, to make sure that functions need to differ in some other way
// to be considered different overloads.
- if (type->basetype == SPIRType::SampledImage ||
- (type->basetype == SPIRType::Image && type->image.sampled == 1) || type->basetype == SPIRType::Sampler)
+ if (type.basetype == SPIRType::SampledImage ||
+ (type.basetype == SPIRType::Image && type.image.sampled == 1) || type.basetype == SPIRType::Sampler)
{
continue;
}
@@ -8866,41 +8920,6 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
current_function = &func;
auto &entry_block = get(func.entry_block);
- if (!func.analyzed_variable_scope)
- {
- analyze_variable_scope(func);
-
- // Check if we can actually use the loop variables we found in analyze_variable_scope.
- // To use multiple initializers, we need the same type and qualifiers.
- for (auto block : func.blocks)
- {
- auto &b = get(block);
- if (b.loop_variables.size() < 2)
- continue;
-
- auto &flags = get_decoration_bitset(b.loop_variables.front());
- uint32_t type = get(b.loop_variables.front()).basetype;
- bool invalid_initializers = false;
- for (auto loop_variable : b.loop_variables)
- {
- if (flags != get_decoration_bitset(loop_variable) ||
- type != get(b.loop_variables.front()).basetype)
- {
- invalid_initializers = true;
- break;
- }
- }
-
- if (invalid_initializers)
- {
- for (auto loop_variable : b.loop_variables)
- get(loop_variable).loop_variable = false;
- b.loop_variables.clear();
- }
- }
- func.analyzed_variable_scope = true;
- }
-
for (auto &v : func.local_variables)
{
auto &var = get(v);
@@ -8927,6 +8946,11 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
entry_block.dominated_variables.push_back(var.self);
var.deferred_declaration = true;
}
+ else if (var.storage == StorageClassFunction && var.remapped_variable && var.static_expression)
+ {
+ // No need to declare this variable, it has a static expression.
+ var.deferred_declaration = false;
+ }
else if (expression_is_lvalue(v))
{
add_local_variable_name(var.self);
@@ -9123,6 +9147,7 @@ void CompilerGLSL::branch(uint32_t from, uint32_t cond, uint32_t true_block, uin
if (true_sub)
{
+ emit_block_hints(get(from));
statement("if (", to_expression(cond), ")");
begin_scope();
branch(from, true_block);
@@ -9146,6 +9171,7 @@ void CompilerGLSL::branch(uint32_t from, uint32_t cond, uint32_t true_block, uin
else if (false_sub && !true_sub)
{
// Only need false path, use negative conditional.
+ emit_block_hints(get(from));
statement("if (!", to_enclosed_expression(cond), ")");
begin_scope();
branch(from, false_block);
@@ -9374,6 +9400,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
{
// This block may be a dominating block, so make sure we flush undeclared variables before building the for loop header.
flush_undeclared_variables(block);
+ emit_block_hints(block);
// Important that we do this in this order because
// emitting the continue block can invalidate the condition expression.
@@ -9392,6 +9419,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
case SPIRBlock::WhileLoop:
// This block may be a dominating block, so make sure we flush undeclared variables before building the while loop header.
flush_undeclared_variables(block);
+ emit_block_hints(block);
statement("while (", to_expression(block.condition), ")");
break;
@@ -9439,11 +9467,13 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
auto initializer = emit_for_loop_initializers(block);
auto condition = to_expression(child.condition);
auto continue_block = emit_continue_block(block.continue_block);
+ emit_block_hints(block);
statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
break;
}
case SPIRBlock::WhileLoop:
+ emit_block_hints(block);
statement("while (", to_expression(child.condition), ")");
break;
@@ -9654,35 +9684,65 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
auto &type = expression_type(block.condition);
bool uint32_t_case = type.basetype == SPIRType::UInt;
+ emit_block_hints(block);
statement("switch (", to_expression(block.condition), ")");
begin_scope();
+ // Multiple case labels can branch to same block, so find all unique blocks.
+ bool emitted_default = false;
+ unordered_set emitted_blocks;
+
for (auto &c : block.cases)
{
- auto case_value =
- uint32_t_case ? convert_to_string(uint32_t(c.value)) : convert_to_string(int32_t(c.value));
- statement("case ", case_value, ":");
+ if (emitted_blocks.count(c.block) != 0)
+ continue;
+
+ // Emit all case labels which branch to our target.
+ // FIXME: O(n^2), revisit if we hit shaders with 100++ case labels ...
+ for (auto &other_case : block.cases)
+ {
+ if (other_case.block == c.block)
+ {
+ auto case_value = uint32_t_case ? convert_to_string(uint32_t(other_case.value)) :
+ convert_to_string(int32_t(other_case.value));
+ statement("case ", case_value, ":");
+ }
+ }
+
+ // Maybe we share with default block?
+ if (block.default_block == c.block)
+ {
+ statement("default:");
+ emitted_default = true;
+ }
+
+ // Complete the target.
+ emitted_blocks.insert(c.block);
+
begin_scope();
branch(block.self, c.block);
end_scope();
}
- if (block.default_block != block.next_block)
+ if (!emitted_default)
{
- statement("default:");
- begin_scope();
- if (is_break(block.default_block))
- SPIRV_CROSS_THROW("Cannot break; out of a switch statement and out of a loop at the same time ...");
- branch(block.self, block.default_block);
- end_scope();
- }
- else if (flush_phi_required(block.self, block.next_block))
- {
- statement("default:");
- begin_scope();
- flush_phi(block.self, block.next_block);
- statement("break;");
- end_scope();
+ if (block.default_block != block.next_block)
+ {
+ statement("default:");
+ begin_scope();
+ if (is_break(block.default_block))
+ SPIRV_CROSS_THROW("Cannot break; out of a switch statement and out of a loop at the same time ...");
+ branch(block.self, block.default_block);
+ end_scope();
+ }
+ else if (flush_phi_required(block.self, block.next_block))
+ {
+ statement("default:");
+ begin_scope();
+ flush_phi(block.self, block.next_block);
+ statement("break;");
+ end_scope();
+ }
}
end_scope();
@@ -9874,3 +9934,70 @@ void CompilerGLSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
{
statement(lhs, " = ", to_expression(rhs_id), ";");
}
+
+void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr,
+ const spirv_cross::SPIRType &expr_type)
+{
+ // Only interested in standalone builtin variables.
+ if (!has_decoration(source_id, DecorationBuiltIn))
+ return;
+
+ auto builtin = static_cast(get_decoration(source_id, DecorationBuiltIn));
+ auto expected_type = expr_type.basetype;
+
+ // TODO: Fill in for more builtins.
+ switch (builtin)
+ {
+ case BuiltInLayer:
+ case BuiltInPrimitiveId:
+ case BuiltInViewportIndex:
+ case BuiltInInstanceId:
+ case BuiltInInstanceIndex:
+ case BuiltInVertexId:
+ case BuiltInVertexIndex:
+ case BuiltInSampleId:
+ expected_type = SPIRType::Int;
+ break;
+
+ default:
+ break;
+ }
+
+ if (expected_type != expr_type.basetype)
+ expr = bitcast_expression(expr_type, expected_type, expr);
+}
+
+void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr,
+ const spirv_cross::SPIRType &expr_type)
+{
+ // Only interested in standalone builtin variables.
+ if (!has_decoration(target_id, DecorationBuiltIn))
+ return;
+
+ auto builtin = static_cast(get_decoration(target_id, DecorationBuiltIn));
+ auto expected_type = expr_type.basetype;
+
+ // TODO: Fill in for more builtins.
+ switch (builtin)
+ {
+ case BuiltInLayer:
+ case BuiltInPrimitiveId:
+ case BuiltInViewportIndex:
+ expected_type = SPIRType::Int;
+ break;
+
+ default:
+ break;
+ }
+
+ if (expected_type != expr_type.basetype)
+ {
+ auto type = expr_type;
+ type.basetype = expected_type;
+ expr = bitcast_expression(type, expr_type.basetype, expr);
+ }
+}
+
+void CompilerGLSL::emit_block_hints(const SPIRBlock &)
+{
+}
diff --git a/deps/SPIRV-Cross/spirv_glsl.hpp b/deps/SPIRV-Cross/spirv_glsl.hpp
index 442a31c602..e426e5061e 100644
--- a/deps/SPIRV-Cross/spirv_glsl.hpp
+++ b/deps/SPIRV-Cross/spirv_glsl.hpp
@@ -106,6 +106,11 @@ public:
// Inverts gl_Position.y or equivalent.
bool flip_vert_y = false;
+
+ // If true, the backend will assume that InstanceIndex will need to apply
+ // a base instance offset. Set to false if you know you will never use base instance
+ // functionality as it might remove some internal uniforms.
+ bool support_nonzero_base_instance = true;
} vertex;
struct
@@ -277,7 +282,6 @@ protected:
{
for (uint32_t i = 0; i < indent; i++)
(*buffer) << " ";
-
statement_inner(std::forward(ts)...);
(*buffer) << '\n';
}
@@ -371,7 +375,7 @@ protected:
void emit_flattened_io_block(const SPIRVariable &var, const char *qual);
void emit_block_chain(SPIRBlock &block);
void emit_hoisted_temporaries(std::vector> &temporaries);
- void emit_specialization_constant(const SPIRConstant &constant);
+ void emit_constant(const SPIRConstant &constant);
void emit_specialization_constant_op(const SPIRConstantOp &constant);
std::string emit_continue_block(uint32_t continue_block);
bool attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method);
@@ -405,6 +409,9 @@ protected:
SPIRType binary_op_bitcast_helper(std::string &cast_op0, std::string &cast_op1, SPIRType::BaseType &input_type,
uint32_t op0, uint32_t op1, bool skip_cast_if_equal_type);
+ std::string to_ternary_expression(const SPIRType &result_type, uint32_t select, uint32_t true_value,
+ uint32_t false_value);
+
void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
bool expression_is_forwarded(uint32_t id);
SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs,
@@ -452,11 +459,12 @@ protected:
const char *format_to_glsl(spv::ImageFormat format);
virtual std::string layout_for_member(const SPIRType &type, uint32_t index);
virtual std::string to_interpolation_qualifiers(const Bitset &flags);
- Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index);
std::string layout_for_variable(const SPIRVariable &variable);
std::string to_combined_image_sampler(uint32_t image_id, uint32_t samp_id);
virtual bool skip_argument(uint32_t id) const;
virtual void emit_array_copy(const std::string &lhs, uint32_t rhs_id);
+ virtual void emit_block_hints(const SPIRBlock &block);
+ virtual std::string to_initializer_expression(const SPIRVariable &var);
bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing, uint32_t start_offset = 0,
uint32_t end_offset = UINT32_MAX);
@@ -485,7 +493,7 @@ protected:
void replace_fragment_output(SPIRVariable &var);
void replace_fragment_outputs();
bool check_explicit_lod_allowed(uint32_t lod);
- std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod);
+ std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id);
uint32_t indent = 0;
@@ -563,6 +571,12 @@ protected:
std::string convert_separate_image_to_combined(uint32_t id);
+ // Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
+ // as either unsigned or signed.
+ // Sometimes we will need to automatically perform bitcasts on load and store to make this work.
+ virtual void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
+ virtual void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
+
private:
void init()
{
diff --git a/deps/SPIRV-Cross/spirv_hlsl.cpp b/deps/SPIRV-Cross/spirv_hlsl.cpp
index b294b79d1d..34e1d19fb5 100644
--- a/deps/SPIRV-Cross/spirv_hlsl.cpp
+++ b/deps/SPIRV-Cross/spirv_hlsl.cpp
@@ -224,7 +224,7 @@ static bool hlsl_opcode_is_sign_invariant(Op opcode)
}
}
-string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
+string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t)
{
auto &imagetype = get(type.image.type);
const char *dim = nullptr;
@@ -275,7 +275,7 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
">");
}
-string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
+string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type, uint32_t id)
{
auto &imagetype = get(type.image.type);
string res;
@@ -338,18 +338,18 @@ string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
res += "MS";
if (type.image.arrayed)
res += "Array";
- if (type.image.depth)
+ if (image_is_comparison(type, id))
res += "Shadow";
return res;
}
-string CompilerHLSL::image_type_hlsl(const SPIRType &type)
+string CompilerHLSL::image_type_hlsl(const SPIRType &type, uint32_t id)
{
if (hlsl_options.shader_model <= 30)
- return image_type_hlsl_legacy(type);
+ return image_type_hlsl_legacy(type, id);
else
- return image_type_hlsl_modern(type);
+ return image_type_hlsl_modern(type, id);
}
// The optional id parameter indicates the object whose type we are trying
@@ -370,10 +370,10 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::Image:
case SPIRType::SampledImage:
- return image_type_hlsl(type);
+ return image_type_hlsl(type, id);
case SPIRType::Sampler:
- return comparison_samplers.count(id) ? "SamplerComparisonState" : "SamplerState";
+ return comparison_ids.count(id) ? "SamplerComparisonState" : "SamplerState";
case SPIRType::Void:
return "void";
@@ -1838,9 +1838,10 @@ void CompilerHLSL::emit_buffer_block(const SPIRVariable &var)
{
Bitset flags = get_buffer_block_flags(var);
bool is_readonly = flags.get(DecorationNonWritable);
+ bool is_coherent = flags.get(DecorationCoherent);
add_resource_name(var.self);
- statement(is_readonly ? "ByteAddressBuffer " : "RWByteAddressBuffer ", to_name(var.self),
- type_to_array_glsl(type), to_resource_binding(var), ";");
+ statement(is_coherent ? "globallycoherent " : "", is_readonly ? "ByteAddressBuffer " : "RWByteAddressBuffer ",
+ to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
}
else
{
@@ -2059,7 +2060,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
{
// Manufacture automatic sampler arg for SampledImage texture
decl += ", ";
- decl += join(arg_type.image.depth ? "SamplerComparisonState " : "SamplerState ",
+ decl += join(image_is_comparison(arg_type, arg.id) ? "SamplerComparisonState " : "SamplerState ",
to_sampler_expression(arg.id), type_to_array_glsl(arg_type));
}
@@ -2574,7 +2575,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
{
texop += img_expr;
- if (imgtype.image.depth)
+ if (image_is_comparison(imgtype, img))
{
if (gather)
{
@@ -2922,13 +2923,17 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
case SPIRType::SampledImage:
case SPIRType::Image:
{
- statement(image_type_hlsl_modern(type), " ", to_name(var.self), type_to_array_glsl(type),
- to_resource_binding(var), ";");
+ bool is_coherent = false;
+ if (type.basetype == SPIRType::Image && type.image.sampled == 2)
+ is_coherent = has_decoration(var.self, DecorationCoherent);
+
+ statement(is_coherent ? "globallycoherent " : "", image_type_hlsl_modern(type, var.self), " ",
+ to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
{
// For combined image samplers, also emit a combined image sampler.
- if (type.image.depth)
+ if (image_is_comparison(type, var.self))
statement("SamplerComparisonState ", to_sampler_expression(var.self), type_to_array_glsl(type),
to_resource_binding_sampler(var), ";");
else
@@ -2939,7 +2944,7 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
}
case SPIRType::Sampler:
- if (comparison_samplers.count(var.self))
+ if (comparison_ids.count(var.self))
statement("SamplerComparisonState ", to_name(var.self), type_to_array_glsl(type), to_resource_binding(var),
";");
else
@@ -3524,14 +3529,8 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
else
base = to_expression(ops[2]);
- auto *basetype = &type;
-
// Start traversing type hierarchy at the proper non-pointer types.
- while (basetype->pointer)
- {
- assert(basetype->parent_type);
- basetype = &get(basetype->parent_type);
- }
+ auto *basetype = &get_non_pointer_type(type);
// Traverse the type hierarchy down to the actual buffer types.
for (uint32_t i = 0; i < to_plain_buffer_length; i++)
@@ -3767,7 +3766,7 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i)
}
// clang-format off
-#define GROUP_OP(op, hlsl_op, supports_scan) \
+#define HLSL_GROUP_OP(op, hlsl_op, supports_scan) \
case OpGroupNonUniform##op: \
{ \
auto operation = static_cast(ops[3]); \
@@ -3787,20 +3786,20 @@ case OpGroupNonUniform##op: \
SPIRV_CROSS_THROW("Invalid group operation."); \
break; \
}
- GROUP_OP(FAdd, Sum, true)
- GROUP_OP(FMul, Product, true)
- GROUP_OP(FMin, Min, false)
- GROUP_OP(FMax, Max, false)
- GROUP_OP(IAdd, Sum, true)
- GROUP_OP(IMul, Product, true)
- GROUP_OP(SMin, Min, false)
- GROUP_OP(SMax, Max, false)
- GROUP_OP(UMin, Min, false)
- GROUP_OP(UMax, Max, false)
- GROUP_OP(BitwiseAnd, BitAnd, false)
- GROUP_OP(BitwiseOr, BitOr, false)
- GROUP_OP(BitwiseXor, BitXor, false)
-#undef GROUP_OP
+ 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(BitwiseAnd, BitAnd, false)
+ HLSL_GROUP_OP(BitwiseOr, BitOr, false)
+ HLSL_GROUP_OP(BitwiseXor, BitXor, false)
+#undef HLSL_GROUP_OP
// clang-format on
case OpGroupNonUniformQuadSwap:
@@ -3839,7 +3838,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
#define HLSL_BOP_CAST(op, type) \
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, hlsl_opcode_is_sign_invariant(opcode))
#define HLSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
-#define HLS_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
+#define HLSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define HLSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define HLSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define HLSL_BFOP_CAST(op, type) \
@@ -4573,6 +4572,7 @@ string CompilerHLSL::compile()
backend.can_declare_arrays_inline = false;
backend.can_return_array = false;
+ build_function_control_flow_graphs_and_analyze();
update_active_builtins();
analyze_image_and_sampler_usage();
@@ -4605,3 +4605,24 @@ string CompilerHLSL::compile()
return buffer->str();
}
+
+void CompilerHLSL::emit_block_hints(const SPIRBlock &block)
+{
+ switch (block.hint)
+ {
+ case SPIRBlock::HintFlatten:
+ statement("[flatten]");
+ break;
+ case SPIRBlock::HintDontFlatten:
+ statement("[branch]");
+ break;
+ case SPIRBlock::HintUnroll:
+ statement("[unroll]");
+ break;
+ case SPIRBlock::HintDontUnroll:
+ statement("[loop]");
+ break;
+ default:
+ break;
+ }
+}
diff --git a/deps/SPIRV-Cross/spirv_hlsl.hpp b/deps/SPIRV-Cross/spirv_hlsl.hpp
index df330d0588..bcc82b1043 100644
--- a/deps/SPIRV-Cross/spirv_hlsl.hpp
+++ b/deps/SPIRV-Cross/spirv_hlsl.hpp
@@ -118,9 +118,9 @@ public:
private:
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
- std::string image_type_hlsl(const SPIRType &type);
- std::string image_type_hlsl_modern(const SPIRType &type);
- std::string image_type_hlsl_legacy(const SPIRType &type);
+ std::string image_type_hlsl(const SPIRType &type, uint32_t id);
+ std::string image_type_hlsl_modern(const SPIRType &type, uint32_t id);
+ std::string image_type_hlsl_legacy(const SPIRType &type, uint32_t id);
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_hlsl_entry_point();
void emit_header() override;
@@ -158,6 +158,7 @@ private:
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;
+ void emit_block_hints(const SPIRBlock &block) override;
void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, const std::string &qualifier,
uint32_t base_offset = 0) override;
diff --git a/deps/SPIRV-Cross/spirv_msl.cpp b/deps/SPIRV-Cross/spirv_msl.cpp
index fe7a345d16..3f8de118b1 100644
--- a/deps/SPIRV-Cross/spirv_msl.cpp
+++ b/deps/SPIRV-Cross/spirv_msl.cpp
@@ -280,6 +280,7 @@ string CompilerMSL::compile()
struct_member_padding.clear();
+ build_function_control_flow_graphs_and_analyze();
update_active_builtins();
analyze_image_and_sampler_usage();
build_implicit_builtins();
@@ -534,19 +535,44 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
// Add the global variables as arguments to the function
if (func_id != entry_point)
{
- uint32_t next_id = increase_bound_by(uint32_t(added_arg_ids.size()));
for (uint32_t arg_id : added_arg_ids)
{
- auto var = get(arg_id);
+ auto &var = get(arg_id);
uint32_t type_id = var.basetype;
- func.add_parameter(type_id, next_id, true);
- set(next_id, type_id, StorageClassFunction, 0, arg_id);
+ auto *p_type = &get(type_id);
- // Ensure the existing variable has a valid name and the new variable has all the same meta info
- set_name(arg_id, ensure_valid_name(to_name(arg_id), "v"));
- meta[next_id] = meta[arg_id];
+ if (is_builtin_variable(var) && p_type->basetype == SPIRType::Struct)
+ {
+ // Get the non-pointer type
+ type_id = get_non_pointer_type_id(type_id);
+ p_type = &get(type_id);
- next_id++;
+ uint32_t mbr_idx = 0;
+ for (auto &mbr_type_id : p_type->member_types)
+ {
+ BuiltIn builtin;
+ bool is_builtin = is_member_builtin(*p_type, mbr_idx, &builtin);
+ if (is_builtin && has_active_builtin(builtin, var.storage))
+ {
+ // Add a arg variable with the same type and decorations as the member
+ uint32_t next_id = increase_bound_by(1);
+ func.add_parameter(mbr_type_id, next_id, true);
+ set(next_id, mbr_type_id, StorageClassFunction);
+ meta[next_id].decoration = meta[type_id].members[mbr_idx];
+ }
+ mbr_idx++;
+ }
+ }
+ else
+ {
+ uint32_t next_id = increase_bound_by(1);
+ func.add_parameter(type_id, next_id, true);
+ set(next_id, type_id, StorageClassFunction, 0, arg_id);
+
+ // Ensure the existing variable has a valid name and the new variable has all the same meta info
+ set_name(arg_id, ensure_valid_name(to_name(arg_id), "v"));
+ meta[next_id] = meta[arg_id];
+ }
}
}
}
@@ -1148,6 +1174,18 @@ void CompilerMSL::emit_custom_functions()
statement("");
break;
+ case SPVFuncImplTexelBufferCoords:
+ {
+ string tex_width_str = convert_to_string(msl_options.texel_buffer_texture_width);
+ statement("// Returns 2D texture coords corresponding to 1D texel buffer coords");
+ statement("uint2 spvTexelBufferCoord(uint tc)");
+ begin_scope();
+ statement(join("return uint2(tc % ", tex_width_str, ", tc / ", tex_width_str, ");"));
+ end_scope();
+ statement("");
+ break;
+ }
+
case SPVFuncImplInverse4x4:
statement("// Returns the determinant of a 2x2 matrix.");
statement("inline float spvDet2x2(float a1, float a2, float b1, float b2)");
@@ -1505,23 +1543,17 @@ void CompilerMSL::emit_specialization_constants()
// Override for MSL-specific syntax instructions
void CompilerMSL::emit_instruction(const Instruction &instruction)
{
-#undef BOP
-#undef BOP_CAST
-#undef UOP
-#undef QFOP
-#undef TFOP
-#undef BFOP
-#undef BFOP_CAST
-#define BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
-#define BOP_CAST(op, type) \
+
+#define MSL_BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
+#define MSL_BOP_CAST(op, type) \
emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
-#define UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
-#define QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
-#define TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
-#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
-#define BFOP_CAST(op, type) \
+#define MSL_UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
+#define MSL_QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
+#define MSL_TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
+#define MSL_BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
+#define MSL_BFOP_CAST(op, type) \
emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
-#define UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
+#define MSL_UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
auto ops = stream(instruction);
auto opcode = static_cast(instruction.op);
@@ -1533,81 +1565,81 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
case OpIEqual:
case OpLogicalEqual:
case OpFOrdEqual:
- BOP(==);
+ MSL_BOP(==);
break;
case OpINotEqual:
case OpLogicalNotEqual:
case OpFOrdNotEqual:
- BOP(!=);
+ MSL_BOP(!=);
break;
case OpUGreaterThan:
case OpSGreaterThan:
case OpFOrdGreaterThan:
- BOP(>);
+ MSL_BOP(>);
break;
case OpUGreaterThanEqual:
case OpSGreaterThanEqual:
case OpFOrdGreaterThanEqual:
- BOP(>=);
+ MSL_BOP(>=);
break;
case OpULessThan:
case OpSLessThan:
case OpFOrdLessThan:
- BOP(<);
+ MSL_BOP(<);
break;
case OpULessThanEqual:
case OpSLessThanEqual:
case OpFOrdLessThanEqual:
- BOP(<=);
+ MSL_BOP(<=);
break;
// Derivatives
case OpDPdx:
case OpDPdxFine:
case OpDPdxCoarse:
- UFOP(dfdx);
+ MSL_UFOP(dfdx);
register_control_dependent_expression(ops[1]);
break;
case OpDPdy:
case OpDPdyFine:
case OpDPdyCoarse:
- UFOP(dfdy);
+ MSL_UFOP(dfdy);
register_control_dependent_expression(ops[1]);
break;
case OpFwidth:
case OpFwidthCoarse:
case OpFwidthFine:
- UFOP(fwidth);
+ MSL_UFOP(fwidth);
register_control_dependent_expression(ops[1]);
break;
// Bitfield
case OpBitFieldInsert:
- QFOP(insert_bits);
+ MSL_QFOP(insert_bits);
break;
case OpBitFieldSExtract:
case OpBitFieldUExtract:
- TFOP(extract_bits);
+ MSL_TFOP(extract_bits);
break;
case OpBitReverse:
- UFOP(reverse_bits);
+ MSL_UFOP(reverse_bits);
break;
case OpBitCount:
- UFOP(popcount);
+ MSL_UFOP(popcount);
break;
case OpFRem:
- BFOP(fmod);
+ MSL_BFOP(fmod);
break;
// Atomics
@@ -1660,7 +1692,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
-#define AFMOImpl(op, valsrc) \
+#define MSL_AFMO_IMPL(op, valsrc) \
do \
{ \
uint32_t result_type = ops[0]; \
@@ -1671,45 +1703,45 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
emit_atomic_func_op(result_type, id, "atomic_fetch_" #op "_explicit", mem_sem, mem_sem, false, ptr, val); \
} while (false)
-#define AFMO(op) AFMOImpl(op, ops[5])
-#define AFMIO(op) AFMOImpl(op, 1)
+#define MSL_AFMO(op) MSL_AFMO_IMPL(op, ops[5])
+#define MSL_AFMIO(op) MSL_AFMO_IMPL(op, 1)
case OpAtomicIIncrement:
- AFMIO(add);
+ MSL_AFMIO(add);
break;
case OpAtomicIDecrement:
- AFMIO(sub);
+ MSL_AFMIO(sub);
break;
case OpAtomicIAdd:
- AFMO(add);
+ MSL_AFMO(add);
break;
case OpAtomicISub:
- AFMO(sub);
+ MSL_AFMO(sub);
break;
case OpAtomicSMin:
case OpAtomicUMin:
- AFMO(min);
+ MSL_AFMO(min);
break;
case OpAtomicSMax:
case OpAtomicUMax:
- AFMO(max);
+ MSL_AFMO(max);
break;
case OpAtomicAnd:
- AFMO(and);
+ MSL_AFMO(and);
break;
case OpAtomicOr:
- AFMO(or);
+ MSL_AFMO(or);
break;
case OpAtomicXor:
- AFMO (xor);
+ MSL_AFMO (xor);
break;
// Images
@@ -1833,7 +1865,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
-#define ImgQry(qrytype) \
+#define MSL_ImgQry(qrytype) \
do \
{ \
uint32_t rslt_type_id = ops[0]; \
@@ -1846,11 +1878,11 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
} while (false)
case OpImageQueryLevels:
- ImgQry(mip_levels);
+ MSL_ImgQry(mip_levels);
break;
case OpImageQuerySamples:
- ImgQry(samples);
+ MSL_ImgQry(samples);
break;
// Casting
@@ -1932,7 +1964,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
e->need_transpose = true;
}
else
- BOP(*);
+ MSL_BOP(*);
break;
}
@@ -2078,6 +2110,11 @@ bool CompilerMSL::maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs)
return false;
auto *var = maybe_get(id_lhs);
+
+ // Is this a remapped, static constant? Don't do anything.
+ if (var->remapped_variable && var->statically_assigned)
+ return true;
+
if (ids[id_rhs].get_type() == TypeConstant && var && var->deferred_declaration)
{
// Special case, if we end up declaring a variable when assigning the constant array,
@@ -2435,8 +2472,9 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (coord_type.vecsize > 1)
tex_coords += ".x";
+ // Metal texel buffer textures are 2D, so convert 1D coord to 2D.
if (is_fetch)
- tex_coords = "uint2(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ", 0)"; // Metal textures are 2D
+ tex_coords = "spvTexelBufferCoord(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ")";
alt_coord = ".y";
@@ -3559,17 +3597,13 @@ std::string CompilerMSL::sampler_type(const SPIRType &type)
SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of samplers.");
// Arrays of samplers in MSL must be declared with a special array syntax ala C++11 std::array.
- auto *parent = &type;
- while (parent->pointer)
- parent = &get(parent->parent_type);
- parent = &get(parent->parent_type);
-
uint32_t array_size =
type.array_size_literal.back() ? type.array.back() : get(type.array.back()).scalar();
-
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of samplers is not supported in MSL.");
- return join("array<", sampler_type(*parent), ", ", array_size, ">");
+
+ auto &parent = get(get_non_pointer_type(type).parent_type);
+ return join("array<", sampler_type(parent), ", ", array_size, ">");
}
else
return "sampler";
@@ -3592,25 +3626,20 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of textures.");
// Arrays of images in MSL must be declared with a special array syntax ala C++11 std::array.
- auto *parent = &type;
- while (parent->pointer)
- parent = &get(parent->parent_type);
- parent = &get(parent->parent_type);
-
uint32_t array_size =
type.array_size_literal.back() ? type.array.back() : get(type.array.back()).scalar();
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of images is not supported in MSL.");
- return join("array<", image_type_glsl(*parent, id), ", ", array_size, ">");
+
+ auto &parent = get(get_non_pointer_type(type).parent_type);
+ return join("array<", image_type_glsl(parent, id), ", ", array_size, ">");
}
string img_type_name;
// Bypass pointers because we need the real image struct
auto &img_type = get(type.self).image;
- bool shadow_image = comparison_images.count(id) != 0;
-
- if (img_type.depth || shadow_image)
+ if (image_is_comparison(type, id))
{
switch (img_type.dim)
{
@@ -4041,14 +4070,15 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
auto &return_type = compiler.get(args[0]);
if (!return_type.array.empty())
return SPVFuncImplArrayCopy;
- else
- return SPVFuncImplNone;
+
+ break;
}
case OpStore:
{
// Get the result type of the RHS. Since this is run as a pre-processing stage,
// we must extract the result type directly from the Instruction, rather than the ID.
+ uint32_t id_lhs = args[0];
uint32_t id_rhs = args[1];
const SPIRType *type = nullptr;
@@ -4060,14 +4090,30 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
else
{
// Or ... an expression.
- if (result_types[id_rhs] != 0)
- type = &compiler.get(result_types[id_rhs]);
+ uint32_t tid = result_types[id_rhs];
+ if (tid)
+ type = &compiler.get(tid);
}
- if (type && compiler.is_array(*type))
+ auto *var = compiler.maybe_get(id_lhs);
+
+ // Are we simply assigning to a statically assigned variable which takes a constant?
+ // Don't bother emitting this function.
+ bool static_expression_lhs =
+ var && var->storage == StorageClassFunction && var->statically_assigned && var->remapped_variable;
+ if (type && compiler.is_array(*type) && !static_expression_lhs)
return SPVFuncImplArrayCopy;
- else
- return SPVFuncImplNone;
+
+ break;
+ }
+
+ case OpImageFetch:
+ {
+ // Retrieve the image type, and if it's a Buffer, emit a texel coordinate function
+ uint32_t tid = result_types[args[2]];
+ if (tid && compiler.get(tid).image.dim == DimBuffer)
+ return SPVFuncImplTexelBufferCoords;
+
break;
}
@@ -4176,7 +4222,7 @@ CompilerMSL::MemberSorter::MemberSorter(SPIRType &t, Meta &m, SortAspect sa)
meta.members.resize(max(type.member_types.size(), meta.members.size()));
}
-void CompilerMSL::remap_constexpr_sampler(uint32_t id, const spirv_cross::MSLConstexprSampler &sampler)
+void CompilerMSL::remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler)
{
auto &type = get(get(id).basetype);
if (type.basetype != SPIRType::SampledImage && type.basetype != SPIRType::Sampler)
@@ -4185,3 +4231,24 @@ void CompilerMSL::remap_constexpr_sampler(uint32_t id, const spirv_cross::MSLCon
SPIRV_CROSS_THROW("Can not remap array of samplers.");
constexpr_samplers[id] = sampler;
}
+
+// MSL always declares builtins with their SPIR-V type.
+void CompilerMSL::bitcast_from_builtin_load(uint32_t, std::string &, const SPIRType &)
+{
+}
+
+void CompilerMSL::bitcast_to_builtin_store(uint32_t, std::string &, const SPIRType &)
+{
+}
+
+std::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.
+ // We will need to inject spvArrayCopy here somehow ...
+ auto &type = get(var.basetype);
+ if (ids[var.initializer].get_type() == TypeConstant && (!type.array.empty() || type.basetype == SPIRType::Struct))
+ return constant_expression(get(var.initializer));
+ else
+ return CompilerGLSL::to_initializer_expression(var);
+}
diff --git a/deps/SPIRV-Cross/spirv_msl.hpp b/deps/SPIRV-Cross/spirv_msl.hpp
index 7af66c9c8a..4d412ace00 100644
--- a/deps/SPIRV-Cross/spirv_msl.hpp
+++ b/deps/SPIRV-Cross/spirv_msl.hpp
@@ -153,6 +153,7 @@ public:
Platform platform = macOS;
uint32_t msl_version = make_msl_version(1, 2);
+ uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
bool enable_point_size_builtin = true;
bool resolve_specialized_array_lengths = true;
@@ -216,6 +217,7 @@ public:
SPVFuncImplFindSMsb,
SPVFuncImplFindUMsb,
SPVFuncImplArrayCopy,
+ SPVFuncImplTexelBufferCoords,
SPVFuncImplInverse4x4,
SPVFuncImplInverse3x3,
SPVFuncImplInverse2x2,
@@ -292,6 +294,7 @@ protected:
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
uint32_t comp, uint32_t sample, bool *p_forward) override;
+ std::string to_initializer_expression(const SPIRVariable &var) override;
std::string unpack_expression_type(std::string expr_str, const SPIRType &type) override;
std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;
bool skip_argument(uint32_t id) const override;
@@ -357,6 +360,9 @@ protected:
void emit_entry_point_declarations() override;
uint32_t builtin_frag_coord_id = 0;
+ void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
+ void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
+
Options msl_options;
std::set spv_function_implementations;
std::unordered_map vtx_attrs_by_location;
diff --git a/deps/SPIRV-Cross/spirv_reflect.cpp b/deps/SPIRV-Cross/spirv_reflect.cpp
new file mode 100644
index 0000000000..c322d972bd
--- /dev/null
+++ b/deps/SPIRV-Cross/spirv_reflect.cpp
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2018 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.
+ * 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 "spirv_reflect.hpp"
+#include "spirv_glsl.hpp"
+#include
+
+using namespace spv;
+using namespace spirv_cross;
+using namespace std;
+
+namespace simple_json
+{
+enum class Type
+{
+ Object,
+ Array,
+};
+
+using State = std::pair;
+using Stack = std::stack;
+
+class Stream
+{
+ Stack stack;
+ std::ostringstream buffer;
+ uint32_t indent{ 0 };
+
+public:
+ void begin_json_object();
+ void end_json_object();
+ void emit_json_key(const std::string &key);
+ void emit_json_key_value(const std::string &key, const std::string &value);
+ void emit_json_key_value(const std::string &key, bool value);
+ void emit_json_key_value(const std::string &key, uint32_t value);
+ void emit_json_key_value(const std::string &key, int32_t value);
+ void emit_json_key_value(const std::string &key, float value);
+ void emit_json_key_object(const std::string &key);
+ void emit_json_key_array(const std::string &key);
+
+ void begin_json_array();
+ void end_json_array();
+ void emit_json_array_value(const std::string &value);
+ void emit_json_array_value(uint32_t value);
+
+ std::string str() const
+ {
+ return buffer.str();
+ }
+
+private:
+ inline void statement_indent()
+ {
+ for (uint32_t i = 0; i < indent; i++)
+ buffer << " ";
+ }
+
+ template
+ inline void statement_inner(T &&t)
+ {
+ buffer << std::forward(t);
+ }
+
+ template
+ inline void statement_inner(T &&t, Ts &&... ts)
+ {
+ buffer << std::forward(t);
+ statement_inner(std::forward(ts)...);
+ }
+
+ template
+ inline void statement(Ts &&... ts)
+ {
+ statement_indent();
+ statement_inner(std::forward(ts)...);
+ buffer << '\n';
+ }
+
+ template
+ void statement_no_return(Ts &&... ts)
+ {
+ statement_indent();
+ statement_inner(std::forward(ts)...);
+ }
+};
+} // namespace simple_json
+
+using namespace simple_json;
+
+// Hackery to emit JSON without using nlohmann/json C++ library (which requires a
+// higher level of compiler compliance than is required by SPIRV-Cross
+void Stream::begin_json_array()
+{
+ if (!stack.empty() && stack.top().second)
+ {
+ statement_inner(",\n");
+ }
+ statement("[");
+ ++indent;
+ stack.emplace(Type::Array, false);
+}
+
+void Stream::end_json_array()
+{
+ if (stack.empty() || stack.top().first != Type::Array)
+ SPIRV_CROSS_THROW("Invalid JSON state");
+ if (stack.top().second)
+ {
+ statement_inner("\n");
+ }
+ --indent;
+ statement_no_return("]");
+ stack.pop();
+ if (!stack.empty())
+ {
+ stack.top().second = true;
+ }
+}
+
+void Stream::emit_json_array_value(const std::string &value)
+{
+ if (stack.empty() || stack.top().first != Type::Array)
+ SPIRV_CROSS_THROW("Invalid JSON state");
+
+ if (stack.top().second)
+ statement_inner(",\n");
+
+ statement_no_return("\"", value, "\"");
+ stack.top().second = true;
+}
+
+void Stream::emit_json_array_value(uint32_t value)
+{
+ if (stack.empty() || stack.top().first != Type::Array)
+ SPIRV_CROSS_THROW("Invalid JSON state");
+ if (stack.top().second)
+ statement_inner(",\n");
+ statement_no_return(std::to_string(value));
+ stack.top().second = true;
+}
+
+void Stream::begin_json_object()
+{
+ if (!stack.empty() && stack.top().second)
+ {
+ statement_inner(",\n");
+ }
+ statement("{");
+ ++indent;
+ stack.emplace(Type::Object, false);
+}
+
+void Stream::end_json_object()
+{
+ if (stack.empty() || stack.top().first != Type::Object)
+ SPIRV_CROSS_THROW("Invalid JSON state");
+ if (stack.top().second)
+ {
+ statement_inner("\n");
+ }
+ --indent;
+ statement_no_return("}");
+ stack.pop();
+ if (!stack.empty())
+ {
+ stack.top().second = true;
+ }
+}
+
+void Stream::emit_json_key(const std::string &key)
+{
+ if (stack.empty() || stack.top().first != Type::Object)
+ SPIRV_CROSS_THROW("Invalid JSON state");
+
+ if (stack.top().second)
+ statement_inner(",\n");
+ statement_no_return("\"", key, "\" : ");
+ stack.top().second = true;
+}
+
+void Stream::emit_json_key_value(const std::string &key, const std::string &value)
+{
+ emit_json_key(key);
+ statement_inner("\"", value, "\"");
+}
+
+void Stream::emit_json_key_value(const std::string &key, uint32_t value)
+{
+ emit_json_key(key);
+ statement_inner(value);
+}
+
+void Stream::emit_json_key_value(const std::string &key, int32_t value)
+{
+ emit_json_key(key);
+ statement_inner(value);
+}
+
+void Stream::emit_json_key_value(const std::string &key, float value)
+{
+ emit_json_key(key);
+ statement_inner(value);
+}
+
+void Stream::emit_json_key_value(const std::string &key, bool value)
+{
+ emit_json_key(key);
+ statement_inner(value ? "true" : "false");
+}
+
+void Stream::emit_json_key_object(const std::string &key)
+{
+ emit_json_key(key);
+ statement_inner("{\n");
+ ++indent;
+ stack.emplace(Type::Object, false);
+}
+
+void Stream::emit_json_key_array(const std::string &key)
+{
+ emit_json_key(key);
+ statement_inner("[\n");
+ ++indent;
+ stack.emplace(Type::Array, false);
+}
+
+void CompilerReflection::set_format(const std::string &format)
+{
+ if (format != "json")
+ {
+ SPIRV_CROSS_THROW("Unsupported format");
+ }
+}
+
+string CompilerReflection::compile()
+{
+ // Force a classic "C" locale, reverts when function returns
+ ClassicLocale classic_locale;
+
+ // Move constructor for this type is broken on GCC 4.9 ...
+ json_stream = std::make_shared();
+ json_stream->begin_json_object();
+ emit_entry_points();
+ emit_types();
+ emit_resources();
+ emit_specialization_constants();
+ json_stream->end_json_object();
+ return json_stream->str();
+}
+
+void CompilerReflection::emit_types()
+{
+ bool emitted_open_tag = false;
+ for (auto &id : ids)
+ {
+ auto idType = id.get_type();
+ if (idType == TypeType)
+ {
+ auto &type = id.get();
+ if (type.basetype == SPIRType::Struct && !type.pointer && type.array.empty())
+ {
+ emit_type(type, emitted_open_tag);
+ }
+ }
+ }
+
+ if (emitted_open_tag)
+ {
+ json_stream->end_json_object();
+ }
+}
+
+void CompilerReflection::emit_type(const SPIRType &type, bool &emitted_open_tag)
+{
+ auto name = type_to_glsl(type);
+
+ if (type.type_alias != 0)
+ return;
+
+ if (!emitted_open_tag)
+ {
+ json_stream->emit_json_key_object("types");
+ emitted_open_tag = true;
+ }
+ json_stream->emit_json_key_object("_" + std::to_string(type.self));
+ json_stream->emit_json_key_value("name", name);
+ json_stream->emit_json_key_array("members");
+ // FIXME ideally we'd like to emit the size of a structure as a
+ // convenience to people parsing the reflected JSON. The problem
+ // is that there's no implicit size for a type. It's final size
+ // will be determined by the top level declaration in which it's
+ // included. So there might be one size for the struct if it's
+ // included in a std140 uniform block and another if it's included
+ // in a std430 uniform block.
+ // The solution is to include *all* potential sizes as a map of
+ // layout type name to integer, but that will probably require
+ // some additional logic being written in this class, or in the
+ // parent CompilerGLSL class.
+ auto size = type.member_types.size();
+ for (uint32_t i = 0; i < size; ++i)
+ {
+ emit_type_member(type, i);
+ }
+ json_stream->end_json_array();
+ json_stream->end_json_object();
+}
+
+void CompilerReflection::emit_type_member(const SPIRType &type, uint32_t index)
+{
+ auto &membertype = get(type.member_types[index]);
+ json_stream->begin_json_object();
+ auto name = to_member_name(type, index);
+ // FIXME we'd like to emit the offset of each member, but such offsets are
+ // context dependent. See the comment above regarding structure sizes
+ json_stream->emit_json_key_value("name", name);
+ if (membertype.basetype == SPIRType::Struct)
+ {
+ json_stream->emit_json_key_value("type", "_" + std::to_string(membertype.self));
+ }
+ else
+ {
+ json_stream->emit_json_key_value("type", type_to_glsl(membertype));
+ }
+ emit_type_member_qualifiers(type, index);
+ json_stream->end_json_object();
+}
+
+void CompilerReflection::emit_type_array(const SPIRType &type)
+{
+ if (!type.array.empty())
+ {
+ json_stream->emit_json_key_array("array");
+ // Note that we emit the zeros here as a means of identifying
+ // unbounded arrays. This is necessary as otherwise there would
+ // be no way of differentiating between float[4] and float[4][]
+ for (const auto &value : type.array)
+ 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 = meta[type.self].members;
+ if (index < memb.size())
+ {
+ auto &dec = memb[index];
+ if (dec.decoration_flags.get(DecorationLocation))
+ json_stream->emit_json_key_value("location", dec.location);
+ if (dec.decoration_flags.get(DecorationOffset))
+ json_stream->emit_json_key_value("offset", dec.offset);
+ }
+}
+
+string CompilerReflection::execution_model_to_str(spv::ExecutionModel model)
+{
+ switch (model)
+ {
+ case spv::ExecutionModelVertex:
+ return "vert";
+ case spv::ExecutionModelTessellationControl:
+ return "tesc";
+ case ExecutionModelTessellationEvaluation:
+ return "tese";
+ case ExecutionModelGeometry:
+ return "geom";
+ case ExecutionModelFragment:
+ return "frag";
+ case ExecutionModelGLCompute:
+ return "comp";
+ default:
+ return "???";
+ }
+}
+
+// FIXME include things like the local_size dimensions, geometry output vertex count, etc
+void CompilerReflection::emit_entry_points()
+{
+ auto entries = get_entry_points_and_stages();
+ if (!entries.empty())
+ {
+ json_stream->emit_json_key_array("entryPoints");
+ for (auto &e : entries)
+ {
+ json_stream->begin_json_object();
+ json_stream->emit_json_key_value("name", e.name);
+ json_stream->emit_json_key_value("mode", execution_model_to_str(e.execution_model));
+ json_stream->end_json_object();
+ }
+ json_stream->end_json_array();
+ }
+}
+
+void CompilerReflection::emit_resources()
+{
+ auto res = get_shader_resources();
+ emit_resources("subpass_inputs", res.subpass_inputs);
+ emit_resources("inputs", res.stage_inputs);
+ emit_resources("outputs", res.stage_outputs);
+ emit_resources("textures", res.sampled_images);
+ emit_resources("separate_images", res.separate_images);
+ emit_resources("separate_samplers", res.separate_samplers);
+ emit_resources("images", res.storage_images);
+ emit_resources("ssbos", res.storage_buffers);
+ emit_resources("ubos", res.uniform_buffers);
+ emit_resources("push_constants", res.push_constant_buffers);
+ emit_resources("counters", res.atomic_counters);
+}
+
+void CompilerReflection::emit_resources(const char *tag, const vector &resources)
+{
+ if (resources.empty())
+ {
+ return;
+ }
+
+ json_stream->emit_json_key_array(tag);
+ for (auto &res : resources)
+ {
+ auto &type = get_type(res.type_id);
+ auto typeflags = meta[type.self].decoration.decoration_flags;
+ auto &mask = get_decoration_bitset(res.id);
+
+ // If we don't have a name, use the fallback for the type instead of the variable
+ // for SSBOs and UBOs since those are the only meaningful names to use externally.
+ // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
+ bool is_push_constant = get_storage_class(res.id) == StorageClassPushConstant;
+ bool is_block = get_decoration_bitset(type.self).get(DecorationBlock) ||
+ get_decoration_bitset(type.self).get(DecorationBufferBlock);
+
+ uint32_t fallback_id = !is_push_constant && is_block ? res.base_type_id : res.id;
+
+ json_stream->begin_json_object();
+
+ if (type.basetype == SPIRType::Struct)
+ {
+ json_stream->emit_json_key_value("type", "_" + std::to_string(res.base_type_id));
+ }
+ else
+ {
+ json_stream->emit_json_key_value("type", type_to_glsl(type));
+ }
+
+ json_stream->emit_json_key_value("name", !res.name.empty() ? res.name : get_fallback_name(fallback_id));
+ {
+ bool ssbo_block = type.storage == StorageClassStorageBuffer ||
+ (type.storage == StorageClassUniform && typeflags.get(DecorationBufferBlock));
+ if (ssbo_block)
+ {
+ auto buffer_flags = get_buffer_block_flags(res.id);
+ if (buffer_flags.get(DecorationNonReadable))
+ json_stream->emit_json_key_value("writeonly", true);
+ if (buffer_flags.get(DecorationNonWritable))
+ json_stream->emit_json_key_value("readonly", true);
+ if (buffer_flags.get(DecorationRestrict))
+ json_stream->emit_json_key_value("restrict", true);
+ if (buffer_flags.get(DecorationCoherent))
+ json_stream->emit_json_key_value("coherent", true);
+ }
+ }
+
+ emit_type_array(type);
+
+ {
+ bool is_sized_block = is_block && (get_storage_class(res.id) == StorageClassUniform ||
+ get_storage_class(res.id) == StorageClassUniformConstant);
+ if (is_sized_block)
+ {
+ uint32_t block_size = uint32_t(get_declared_struct_size(get_type(res.base_type_id)));
+ json_stream->emit_json_key_value("block_size", block_size);
+ }
+ }
+
+ if (type.storage == StorageClassPushConstant)
+ json_stream->emit_json_key_value("push_constant", true);
+ if (mask.get(DecorationLocation))
+ json_stream->emit_json_key_value("location", get_decoration(res.id, DecorationLocation));
+ if (mask.get(DecorationRowMajor))
+ json_stream->emit_json_key_value("row_major", true);
+ if (mask.get(DecorationColMajor))
+ json_stream->emit_json_key_value("column_major", true);
+ if (mask.get(DecorationIndex))
+ json_stream->emit_json_key_value("index", get_decoration(res.id, DecorationIndex));
+ if (type.storage != StorageClassPushConstant && mask.get(DecorationDescriptorSet))
+ json_stream->emit_json_key_value("set", get_decoration(res.id, DecorationDescriptorSet));
+ if (mask.get(DecorationBinding))
+ json_stream->emit_json_key_value("binding", get_decoration(res.id, DecorationBinding));
+ if (mask.get(DecorationInputAttachmentIndex))
+ json_stream->emit_json_key_value("input_attachment_index",
+ get_decoration(res.id, DecorationInputAttachmentIndex));
+ if (mask.get(DecorationOffset))
+ json_stream->emit_json_key_value("offset", get_decoration(res.id, DecorationOffset));
+
+ // For images, the type itself adds a layout qualifer.
+ // Only emit the format for storage images.
+ if (type.basetype == SPIRType::Image && type.image.sampled == 2)
+ {
+ const char *fmt = format_to_glsl(type.image.format);
+ if (fmt != nullptr)
+ json_stream->emit_json_key_value("format", std::string(fmt));
+ }
+ json_stream->end_json_object();
+ }
+ json_stream->end_json_array();
+}
+
+void CompilerReflection::emit_specialization_constants()
+{
+ auto specialization_constants = get_specialization_constants();
+ if (specialization_constants.empty())
+ return;
+
+ json_stream->emit_json_key_array("specialization_constants");
+ for (const auto spec_const : specialization_constants)
+ {
+ auto &c = get(spec_const.id);
+ auto type = get(c.constant_type);
+ 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));
+ switch (type.basetype)
+ {
+ case SPIRType::UInt:
+ json_stream->emit_json_key_value("default_value", c.scalar());
+ break;
+
+ case SPIRType::Int:
+ json_stream->emit_json_key_value("default_value", c.scalar_i32());
+ break;
+
+ case SPIRType::Float:
+ json_stream->emit_json_key_value("default_value", c.scalar_f32());
+ break;
+
+ case SPIRType::Boolean:
+ json_stream->emit_json_key_value("default_value", c.scalar() != 0);
+ break;
+
+ default:
+ break;
+ }
+ json_stream->end_json_object();
+ }
+ json_stream->end_json_array();
+}
+
+string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const
+{
+ auto &memb = meta[type.self].members;
+ if (index < memb.size() && !memb[index].alias.empty())
+ return memb[index].alias;
+ else
+ return join("_m", index);
+}
diff --git a/deps/SPIRV-Cross/spirv_reflect.hpp b/deps/SPIRV-Cross/spirv_reflect.hpp
new file mode 100644
index 0000000000..e402fa8fb9
--- /dev/null
+++ b/deps/SPIRV-Cross/spirv_reflect.hpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 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.
+ * 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 SPIRV_CROSS_REFLECT_HPP
+#define SPIRV_CROSS_REFLECT_HPP
+
+#include "spirv_glsl.hpp"
+#include
+#include
+
+namespace simple_json
+{
+class Stream;
+}
+
+namespace spirv_cross
+{
+class CompilerReflection : public CompilerGLSL
+{
+ using Parent = CompilerGLSL;
+
+public:
+ CompilerReflection(std::vector spirv_)
+ : Parent(move(spirv_))
+ {
+ options.vulkan_semantics = true;
+ }
+
+ CompilerReflection(const uint32_t *ir, size_t word_count)
+ : Parent(ir, word_count)
+ {
+ options.vulkan_semantics = true;
+ }
+
+ void set_format(const std::string &format);
+ std::string compile() override;
+
+private:
+ static std::string execution_model_to_str(spv::ExecutionModel model);
+
+ void emit_entry_points();
+ void emit_types();
+ void emit_resources();
+ void emit_specialization_constants();
+
+ void emit_type(const SPIRType &type, bool &emitted_open_tag);
+ void emit_type_member(const SPIRType &type, uint32_t index);
+ void emit_type_member_qualifiers(const SPIRType &type, uint32_t index);
+ void emit_type_array(const SPIRType &type);
+ void emit_resources(const char *tag, const std::vector &resources);
+
+ std::string to_member_name(const SPIRType &type, uint32_t index) const;
+
+ std::shared_ptr json_stream;
+};
+
+} // namespace spirv_cross
+
+#endif
diff --git a/deps/SPIRV-Cross/test_shaders.py b/deps/SPIRV-Cross/test_shaders.py
index 3efcf923d1..40e1c2e2c3 100755
--- a/deps/SPIRV-Cross/test_shaders.py
+++ b/deps/SPIRV-Cross/test_shaders.py
@@ -11,8 +11,13 @@ import hashlib
import shutil
import argparse
import codecs
+import json
+import multiprocessing
+import errno
+from functools import partial
-force_no_external_validation = False
+backend = 'glsl'
+args = {}
def remove_file(path):
#print('Removing file:', path)
@@ -78,7 +83,7 @@ def print_msl_compiler_version():
subprocess.check_call(['xcrun', '--sdk', 'iphoneos', 'metal', '--version'])
print('...are the Metal compiler characteristics.\n') # display after so xcrun FNF is silent
except OSError as e:
- if (e.errno != os.errno.ENOENT): # Ignore xcrun not found error
+ if (e.errno != errno.ENOENT): # Ignore xcrun not found error
raise
def validate_shader_msl(shader, opt):
@@ -90,7 +95,7 @@ def validate_shader_msl(shader, opt):
subprocess.check_call(['xcrun', '--sdk', msl_os, 'metal', '-x', 'metal', '-std=osx-metal{}'.format('2.0' if msl2 else '1.2'), '-Werror', '-Wno-unused-variable', msl_path])
print('Compiled Metal shader: ' + msl_path) # display after so xcrun FNF is silent
except OSError as oe:
- if (oe.errno != os.errno.ENOENT): # Ignore xcrun not found error
+ if (oe.errno != errno.ENOENT): # Ignore xcrun not found error
raise
except subprocess.CalledProcessError:
print('Error compiling Metal shader: ' + msl_path)
@@ -140,7 +145,7 @@ def shader_to_win_path(shader):
stdout_data, stderr_data = f.communicate()
return stdout_data.decode('utf-8')
except OSError as oe:
- if (oe.errno != os.errno.ENOENT): # Ignore not found errors
+ if (oe.errno != errno.ENOENT): # Ignore not found errors
return shader
except subprocess.CalledProcessError:
raise
@@ -152,12 +157,12 @@ def validate_shader_hlsl(shader):
subprocess.check_call(['glslangValidator', '-e', 'main', '-D', '--target-env', 'vulkan1.1', '-V', shader])
is_no_fxc = '.nofxc.' in shader
global ignore_fxc
- if (not ignore_fxc) and (not force_no_external_validation) and (not is_no_fxc):
+ if (not ignore_fxc) and (not args.force_no_external_validation) and (not is_no_fxc):
try:
win_path = shader_to_win_path(shader)
subprocess.check_call(['fxc', '-nologo', shader_model_hlsl(shader), win_path])
except OSError as oe:
- if (oe.errno != os.errno.ENOENT): # Ignore not found errors
+ if (oe.errno != errno.ENOENT): # Ignore not found errors
raise
else:
ignore_fxc = True
@@ -199,6 +204,24 @@ def cross_compile_hlsl(shader, spirv, opt):
return (spirv_path, hlsl_path)
+def cross_compile_reflect(shader, spirv, opt):
+ spirv_path = create_temporary()
+ reflect_path = create_temporary(os.path.basename(shader))
+
+ if spirv:
+ subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
+ else:
+ subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', '-o', spirv_path, shader])
+
+ if opt:
+ subprocess.check_call(['spirv-opt', '-O', '-o', spirv_path, spirv_path])
+
+ spirv_cross_path = './spirv-cross'
+
+ sm = shader_to_sm(shader)
+ subprocess.check_call([spirv_cross_path, '--entry', 'main', '--output', reflect_path, spirv_path, '--reflect'])
+ return (spirv_path, reflect_path)
+
def validate_shader(shader, vulkan):
if vulkan:
subprocess.check_call(['glslangValidator', '--target-env', 'vulkan1.1', '-V', shader])
@@ -277,6 +300,58 @@ def reference_path(directory, relpath, opt):
reference_dir = os.path.join(reference_dir, split_paths[1])
return os.path.join(reference_dir, relpath)
+def json_ordered(obj):
+ if isinstance(obj, dict):
+ return sorted((k, json_ordered(v)) for k, v in obj.items())
+ if isinstance(obj, list):
+ return sorted(json_ordered(x) for x in obj)
+ else:
+ return obj
+
+def json_compare(json_a, json_b):
+ return json_ordered(json_a) == json_ordered(json_b)
+
+def regression_check_reflect(shader, json_file, update, keep, opt):
+ reference = reference_path(shader[0], shader[1], opt) + '.json'
+ joined_path = os.path.join(shader[0], shader[1])
+ print('Reference shader reflection path:', reference)
+ if os.path.exists(reference):
+ actual = ''
+ expected = ''
+ with open(json_file) as f:
+ actual_json = f.read();
+ actual = json.loads(actual_json)
+ with open(reference) as f:
+ expected = json.load(f)
+ if (json_compare(actual, expected) != True):
+ if update:
+ print('Generated reflection json has changed for {}!'.format(reference))
+ # If we expect changes, update the reference file.
+ if os.path.exists(reference):
+ remove_file(reference)
+ make_reference_dir(reference)
+ shutil.move(json_file, reference)
+ else:
+ print('Generated reflection json in {} does not match reference {}!'.format(json_file, reference))
+ with open(json_file, 'r') as f:
+ print('')
+ print('Generated:')
+ print('======================')
+ print(f.read())
+ print('======================')
+ print('')
+
+ # Otherwise, fail the test. Keep the shader file around so we can inspect.
+ if not keep:
+ remove_file(json_file)
+ sys.exit(1)
+ else:
+ remove_file(json_file)
+ else:
+ print('Found new shader {}. Placing generated source code in {}'.format(joined_path, reference))
+ make_reference_dir(reference)
+ shutil.move(json_file, reference)
+
def regression_check(shader, glsl, update, keep, opt):
reference = reference_path(shader[0], shader[1], opt)
joined_path = os.path.join(shader[0], shader[1])
@@ -396,7 +471,7 @@ def test_shader_msl(stats, shader, update, keep, opt):
# executable from Xcode using args: `--msl --entry main --output msl_path spirv_path`.
# print('SPRIV shader: ' + spirv)
- if not force_no_external_validation:
+ if not args.force_no_external_validation:
validate_shader_msl(shader, opt)
remove_file(spirv)
@@ -410,26 +485,50 @@ def test_shader_hlsl(stats, shader, update, keep, opt):
regression_check(shader, hlsl, update, keep, opt)
remove_file(spirv)
-def test_shaders_helper(stats, shader_dir, update, malisc, keep, opt, backend):
- for root, dirs, files in os.walk(os.path.join(shader_dir)):
+def test_shader_reflect(stats, shader, update, keep, opt):
+ joined_path = os.path.join(shader[0], shader[1])
+ print('Testing shader reflection:', joined_path)
+ is_spirv = shader_is_spirv(shader[1])
+ noopt = shader_is_noopt(shader[1])
+ spirv, reflect = cross_compile_reflect(joined_path, is_spirv, opt and (not noopt))
+ regression_check_reflect(shader, reflect, update, keep, opt)
+ remove_file(spirv)
+
+def test_shader_file(relpath, stats, shader_dir, update, keep, opt, backend):
+ if backend == 'msl':
+ test_shader_msl(stats, (shader_dir, relpath), update, keep, opt)
+ elif backend == 'hlsl':
+ test_shader_hlsl(stats, (shader_dir, relpath), update, keep, opt)
+ elif backend == 'reflect':
+ test_shader_reflect(stats, (shader_dir, relpath), update, keep, opt)
+ else:
+ test_shader(stats, (shader_dir, relpath), update, keep, opt)
+
+def test_shaders_helper(stats):
+ all_files = []
+ for root, dirs, files in os.walk(os.path.join(args.folder)):
files = [ f for f in files if not f.startswith(".") ] #ignore system files (esp OSX)
for i in files:
path = os.path.join(root, i)
- relpath = os.path.relpath(path, shader_dir)
- if backend == 'msl':
- test_shader_msl(stats, (shader_dir, relpath), update, keep, opt)
- elif backend == 'hlsl':
- test_shader_hlsl(stats, (shader_dir, relpath), update, keep, opt)
- else:
- test_shader(stats, (shader_dir, relpath), update, keep, opt)
+ relpath = os.path.relpath(path, args.folder)
+ all_files.append(relpath)
-def test_shaders(shader_dir, update, malisc, keep, opt, backend):
- if malisc:
+ # The child processes in parallel execution mode don't have the proper state for the global args variable, so
+ # at this point we need to switch to explicit arguments
+ if args.parallel:
+ pool = multiprocessing.Pool(multiprocessing.cpu_count())
+ pool.map(partial(test_shader_file, stats=stats, shader_dir=args.folder, update=args.update, keep=args.keep, opt=args.opt, backend=backend), all_files)
+ else:
+ for i in all_files:
+ test_shader_file(i, stats, args.folder, args.update, args.keep, args.opt, backend)
+
+def test_shaders():
+ if args.malisc:
with open('stats.csv', 'w') as stats:
print('Shader,OrigRegs,OrigUniRegs,OrigALUShort,OrigLSShort,OrigTEXShort,OrigALULong,OrigLSLong,OrigTEXLong,CrossRegs,CrossUniRegs,CrossALUShort,CrossLSShort,CrossTEXShort,CrossALULong,CrossLSLong,CrossTEXLong', file = stats)
- test_shaders_helper(stats, shader_dir, update, malisc, keep, backend)
+ test_shaders_helper(stats)
else:
- test_shaders_helper(None, shader_dir, update, malisc, keep, opt, backend)
+ test_shaders_helper(None)
def main():
parser = argparse.ArgumentParser(description = 'Script for regression testing.')
@@ -459,19 +558,35 @@ def main():
parser.add_argument('--opt',
action = 'store_true',
help = 'Run SPIRV-Tools optimization passes as well.')
+ parser.add_argument('--reflect',
+ action = 'store_true',
+ help = 'Test reflection backend.')
+ parser.add_argument('--parallel',
+ action = 'store_true',
+ help = 'Execute tests in parallel. Useful for doing regression quickly, but bad for debugging and stat output.')
+
+ global args
args = parser.parse_args()
-
if not args.folder:
sys.stderr.write('Need shader folder.\n')
sys.exit(1)
+ if (args.parallel and (args.malisc or args.force_no_external_validation or args.update)):
+ sys.stderr.write('Parallel execution is disabled when using the flags --update, --malisc or --force-no-external-validation\n')
+ args.parallel = False
+
if args.msl:
print_msl_compiler_version()
- global force_no_external_validation
- force_no_external_validation = args.force_no_external_validation
+ global backend
+ if (args.msl or args.metal):
+ backend = 'msl'
+ elif args.hlsl:
+ backend = 'hlsl'
+ elif args.reflect:
+ backend = 'reflect'
- test_shaders(args.folder, args.update, args.malisc, args.keep, args.opt, 'msl' if (args.msl or args.metal) else ('hlsl' if args.hlsl else 'glsl'))
+ test_shaders()
if args.malisc:
print('Stats in stats.csv!')
print('Tests completed!')
diff --git a/deps/SPIRV-Cross/test_shaders.sh b/deps/SPIRV-Cross/test_shaders.sh
index e96978a1e6..8a43afb4df 100755
--- a/deps/SPIRV-Cross/test_shaders.sh
+++ b/deps/SPIRV-Cross/test_shaders.sh
@@ -16,4 +16,5 @@ echo "Using spirv-opt in: $(which spirv-opt)."
./test_shaders.py shaders-hlsl --hlsl || exit 1
./test_shaders.py shaders-hlsl --hlsl --opt || exit 1
./test_shaders.py shaders-hlsl-no-opt --hlsl || exit 1
+./test_shaders.py shaders-reflection --reflect || exit 1
diff --git a/deps/SPIRV-Cross/update_test_shaders.sh b/deps/SPIRV-Cross/update_test_shaders.sh
index 4bc87a1564..1582c6c3f3 100755
--- a/deps/SPIRV-Cross/update_test_shaders.sh
+++ b/deps/SPIRV-Cross/update_test_shaders.sh
@@ -16,5 +16,6 @@ echo "Using spirv-opt in: $(which spirv-opt)."
./test_shaders.py shaders-hlsl --update --hlsl || exit 1
./test_shaders.py shaders-hlsl --update --hlsl --opt || exit 1
./test_shaders.py shaders-hlsl-no-opt --update --hlsl || exit 1
+./test_shaders.py shaders-reflection --reflect --update || exit 1
diff --git a/file_path_special.c b/file_path_special.c
index 85313af6b4..fa6c3690a8 100644
--- a/file_path_special.c
+++ b/file_path_special.c
@@ -130,6 +130,10 @@ bool fill_pathname_application_data(char *s, size_t len)
const char* xmb_theme_ident(void);
#endif
+#ifdef HAVE_STRIPES
+const char* stripes_theme_ident(void);
+#endif
+
void fill_pathname_application_special(char *s,
size_t len, enum application_special_type type)
{
diff --git a/gfx/common/metal/Context.h b/gfx/common/metal/Context.h
index b410d8eff8..497da8e44d 100644
--- a/gfx/common/metal/Context.h
+++ b/gfx/common/metal/Context.h
@@ -8,23 +8,61 @@
#import
#import
+#import "RendererCommon.h"
-NS_ASSUME_NONNULL_BEGIN
+@interface Texture : NSObject
+@property (nonatomic, readonly) id texture;
+@property (nonatomic, readonly) id sampler;
+@end
+typedef struct
+{
+ void *data;
+ NSUInteger offset;
+ __unsafe_unretained id