diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c8d795..ad852f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,8 @@ cmake_minimum_required(VERSION 2.8) project(SPIRV-Cross) enable_testing() +option(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS "Instead of throwing exceptions assert" OFF) + if(${CMAKE_GENERATOR} MATCHES "Makefile") if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) message(FATAL_ERROR "Build out of tree to avoid overwriting Makefile") @@ -50,24 +52,35 @@ target_link_libraries(spirv-cross-msl spirv-cross-glsl) target_link_libraries(spirv-cross-cpp spirv-cross-glsl) target_include_directories(spirv-cross-core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +set(spirv-compiler-options "") +set(spirv-compiler-defines "") + +if(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS) + set(spirv-compiler-defines ${spirv-compiler-defines} SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS) +endif() + # To specify special debug or optimization options, use # -DCMAKE_CXX_COMPILE_FLAGS # However, we require the C++11 dialect. if (NOT "${MSVC}") - set(spirv-compiler-options -std=c++11 -Wall -Wextra -Werror -Wshadow) - set(spirv-compiler-defines __STDC_LIMIT_MACROS) - target_compile_options(spirv-cross-core PRIVATE ${spirv-compiler-options}) - target_compile_options(spirv-cross-glsl PRIVATE ${spirv-compiler-options}) - target_compile_options(spirv-cross-msl PRIVATE ${spirv-compiler-options}) - target_compile_options(spirv-cross-cpp PRIVATE ${spirv-compiler-options}) - target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options}) - target_compile_definitions(spirv-cross-core PRIVATE ${spirv-compiler-defines}) - target_compile_definitions(spirv-cross-glsl PRIVATE ${spirv-compiler-defines}) - target_compile_definitions(spirv-cross-msl PRIVATE ${spirv-compiler-defines}) - target_compile_definitions(spirv-cross-cpp PRIVATE ${spirv-compiler-defines}) - target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines}) -endif(NOT "${MSVC}") + set(spirv-compiler-options ${spirv-compiler-options} -std=c++11 -Wall -Wextra -Werror -Wshadow) + set(spirv-compiler-defines ${spirv-compiler-defines} __STDC_LIMIT_MACROS) + if(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS) + set(spirv-compiler-options ${spirv-compiler-options} -fno-exceptions) + endif() +endif() + +target_compile_options(spirv-cross-core PRIVATE ${spirv-compiler-options}) +target_compile_options(spirv-cross-glsl PRIVATE ${spirv-compiler-options}) +target_compile_options(spirv-cross-msl PRIVATE ${spirv-compiler-options}) +target_compile_options(spirv-cross-cpp PRIVATE ${spirv-compiler-options}) +target_compile_options(spirv-cross PRIVATE ${spirv-compiler-options}) +target_compile_definitions(spirv-cross-core PRIVATE ${spirv-compiler-defines}) +target_compile_definitions(spirv-cross-glsl PRIVATE ${spirv-compiler-defines}) +target_compile_definitions(spirv-cross-msl PRIVATE ${spirv-compiler-defines}) +target_compile_definitions(spirv-cross-cpp PRIVATE ${spirv-compiler-defines}) +target_compile_definitions(spirv-cross PRIVATE ${spirv-compiler-defines}) # Set up tests, using only the simplest modes of the test_shaders # script. You have to invoke the script manually to: @@ -80,5 +93,6 @@ if(${PYTHONINTERP_FOUND} AND ${PYTHON_VERSION_MAJOR} GREATER 2) COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py ${CMAKE_CURRENT_SOURCE_DIR}/shaders) else() - message(WARNING "Testing disabled. Could not find python3") + message(WARNING "Testing disabled. Could not find python3. If you have python3 installed try running " + "cmake with -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python3 to help it find the executable") endif() diff --git a/Makefile b/Makefile index 485cea9..0564b65 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,11 @@ CXXFLAGS += -std=c++11 -Wall -Wextra -Wshadow -D__STDC_LIMIT_MACROS ifeq ($(DEBUG), 1) CXXFLAGS += -O0 -g else - CXXFLAGS += -O2 -g + CXXFLAGS += -O2 -DNDEBUG +endif + +ifeq ($(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS), 1) + CXXFLAGS += -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS -fno-exceptions endif all: $(TARGET) diff --git a/README.md b/README.md index a7f097f..415f952 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ However, most missing features are expected to be "trivial" improvements at this SPIRV-Cross has been tested on Linux, OSX and Windows. +The make and CMake build flavors offer the option to treat exceptions as assertions. To disable exceptions for make just append SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=1 to the command line. For CMake append -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=ON. By default exceptions are enabled. + ### Linux and macOS Just run `make` on the command line. A recent GCC (4.8+) or Clang (3.x+) compiler is required as SPIRV-Cross uses C++11 extensively. diff --git a/main.cpp b/main.cpp index f80f03e..840b0f2 100644 --- a/main.cpp +++ b/main.cpp @@ -30,6 +30,17 @@ using namespace spv; using namespace spirv_cross; using namespace std; +#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS +#define THROW(x) \ + do \ + { \ + fprintf(stderr, "%s.", x); \ + exit(1); \ + } while (0) +#else +#define THROW(x) runtime_error(x) +#endif + struct CLIParser; struct CLICallbacks { @@ -53,7 +64,9 @@ struct CLIParser bool parse() { +#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS try +#endif { while (argc && !ended_state) { @@ -69,7 +82,7 @@ struct CLIParser auto itr = cbs.callbacks.find(next); if (itr == ::end(cbs.callbacks)) { - throw logic_error("Invalid argument.\n"); + THROW("Invalid argument"); } itr->second(*this); @@ -78,6 +91,7 @@ struct CLIParser return true; } +#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS catch (...) { if (cbs.error_handler) @@ -86,6 +100,7 @@ struct CLIParser } return false; } +#endif } void end() @@ -97,13 +112,13 @@ struct CLIParser { if (!argc) { - throw logic_error("Tried to parse uint, but nothing left in arguments.\n"); + THROW("Tried to parse uint, but nothing left in arguments"); } uint32_t val = stoul(*argv); if (val > numeric_limits::max()) { - throw out_of_range("next_uint() out of range.\n"); + THROW("next_uint() out of range"); } argc--; @@ -116,7 +131,7 @@ struct CLIParser { if (!argc) { - throw logic_error("Tried to parse double, but nothing left in arguments.\n"); + THROW("Tried to parse double, but nothing left in arguments"); } double val = stod(*argv); @@ -131,7 +146,7 @@ struct CLIParser { if (!argc) { - throw logic_error("Tried to parse string, but nothing left in arguments.\n"); + THROW("Tried to parse string, but nothing left in arguments"); } const char *ret = *argv; diff --git a/spirv_common.hpp b/spirv_common.hpp index bfc6ad2..84257d5 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -17,13 +17,31 @@ #ifndef SPIRV_CROSS_COMMON_HPP #define SPIRV_CROSS_COMMON_HPP +#include +#include #include #include -#include -#include namespace spirv_cross { + +#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS +#ifndef _MSC_VER +[[noreturn]] +#endif + inline void + report_and_abort(const std::string &msg) +{ +#ifdef NDEBUG + (void)msg; +#else + fprintf(stderr, "There was a compiler error: %s\n", msg.c_str()); +#endif + abort(); +} + +#define SPIRV_CROSS_THROW(x) report_and_abort(x) +#else class CompilerError : public std::runtime_error { public: @@ -33,6 +51,9 @@ public: } }; +#define SPIRV_CROSS_THROW(x) throw CompilerError(x) +#endif + namespace inner { template @@ -792,7 +813,7 @@ public: { holder = std::move(val); if (type != TypeNone && type != new_type) - throw CompilerError("Overwriting a variant with new type."); + SPIRV_CROSS_THROW("Overwriting a variant with new type."); type = new_type; } @@ -800,9 +821,9 @@ public: T &get() { if (!holder) - throw CompilerError("nullptr"); + SPIRV_CROSS_THROW("nullptr"); if (T::type != type) - throw CompilerError("Bad cast"); + SPIRV_CROSS_THROW("Bad cast"); return *static_cast(holder.get()); } @@ -810,9 +831,9 @@ public: const T &get() const { if (!holder) - throw CompilerError("nullptr"); + SPIRV_CROSS_THROW("nullptr"); if (T::type != type) - throw CompilerError("Bad cast"); + SPIRV_CROSS_THROW("Bad cast"); return *static_cast(holder.get()); } diff --git a/spirv_cpp.cpp b/spirv_cpp.cpp index ae1737f..223a954 100644 --- a/spirv_cpp.cpp +++ b/spirv_cpp.cpp @@ -116,8 +116,8 @@ void CompilerCPP::emit_push_constant_block(const SPIRVariable &var) auto &type = get(var.basetype); auto &flags = meta[var.self].decoration.decoration_flags; if ((flags & (1ull << DecorationBinding)) || (flags & (1ull << DecorationDescriptorSet))) - throw CompilerError("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. " - "Remap to location with reflection API first or disable these decorations."); + SPIRV_CROSS_THROW("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. " + "Remap to location with reflection API first or disable these decorations."); emit_block_struct(type); auto buffer_name = to_name(type.self); @@ -298,7 +298,7 @@ string CompilerCPP::compile() do { if (pass_count >= 3) - throw CompilerError("Over 3 compilation loops detected. Must be a bug!"); + SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!"); resource_registrations.clear(); reset(); @@ -469,7 +469,7 @@ void CompilerCPP::emit_header() break; default: - throw CompilerError("Unsupported execution model."); + SPIRV_CROSS_THROW("Unsupported execution model."); } switch (execution.model) @@ -506,6 +506,6 @@ void CompilerCPP::emit_header() break; default: - throw CompilerError("Unsupported execution model."); + SPIRV_CROSS_THROW("Unsupported execution model."); } } diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 6413057..7b2d983 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -33,7 +33,7 @@ Instruction::Instruction(const vector &spirv, uint32_t &index) count = (spirv[index] >> 16) & 0xffff; if (count == 0) - throw CompilerError("SPIR-V instructions cannot consume 0 words. Invalid SPIR-V file."); + SPIRV_CROSS_THROW("SPIR-V instructions cannot consume 0 words. Invalid SPIR-V file."); offset = index + 1; length = count - 1; @@ -41,7 +41,7 @@ Instruction::Instruction(const vector &spirv, uint32_t &index) index += count; if (index > spirv.size()) - throw CompilerError("SPIR-V instruction goes out of bounds."); + SPIRV_CROSS_THROW("SPIR-V instruction goes out of bounds."); } Compiler::Compiler(vector ir) @@ -328,7 +328,7 @@ const SPIRType &Compiler::expression_type(uint32_t id) const return get(get(id).basetype); default: - throw CompilerError("Cannot resolve expression type."); + SPIRV_CROSS_THROW("Cannot resolve expression type."); } } @@ -665,7 +665,7 @@ static string extract_string(const vector &spirv, uint32_t offset) } } - throw CompilerError("String was not terminated before EOF"); + SPIRV_CROSS_THROW("String was not terminated before EOF"); } static bool is_valid_spirv_version(uint32_t version) @@ -687,7 +687,7 @@ void Compiler::parse() { auto len = spirv.size(); if (len < 5) - throw CompilerError("SPIRV file too small."); + SPIRV_CROSS_THROW("SPIRV file too small."); auto s = spirv.data(); @@ -696,7 +696,7 @@ void Compiler::parse() transform(begin(spirv), end(spirv), begin(spirv), [](uint32_t c) { return swap_endian(c); }); if (s[0] != MagicNumber || !is_valid_spirv_version(s[1])) - throw CompilerError("Invalid SPIRV format."); + SPIRV_CROSS_THROW("Invalid SPIRV format."); uint32_t bound = s[3]; ids.resize(bound); @@ -710,9 +710,9 @@ void Compiler::parse() parse(i); if (current_function) - throw CompilerError("Function was not terminated."); + SPIRV_CROSS_THROW("Function was not terminated."); if (current_block) - throw CompilerError("Block was not terminated."); + SPIRV_CROSS_THROW("Block was not terminated."); } void Compiler::flatten_interface_block(uint32_t id) @@ -722,24 +722,24 @@ void Compiler::flatten_interface_block(uint32_t id) auto flags = meta.at(type.self).decoration.decoration_flags; if (!type.array.empty()) - throw CompilerError("Type is array of UBOs."); + SPIRV_CROSS_THROW("Type is array of UBOs."); if (type.basetype != SPIRType::Struct) - throw CompilerError("Type is not a struct."); + SPIRV_CROSS_THROW("Type is not a struct."); if ((flags & (1ull << DecorationBlock)) == 0) - throw CompilerError("Type is not a block."); + SPIRV_CROSS_THROW("Type is not a block."); if (type.member_types.empty()) - throw CompilerError("Member list of struct is empty."); + SPIRV_CROSS_THROW("Member list of struct is empty."); uint32_t t = type.member_types[0]; for (auto &m : type.member_types) if (t != m) - throw CompilerError("Types in block differ."); + SPIRV_CROSS_THROW("Types in block differ."); auto &mtype = get(t); if (!mtype.array.empty()) - throw CompilerError("Member type cannot be arrays."); + SPIRV_CROSS_THROW("Member type cannot be arrays."); if (mtype.basetype == SPIRType::Struct) - throw CompilerError("Member type cannot be struct."); + SPIRV_CROSS_THROW("Member type cannot be struct."); // Inherit variable name from interface block name. meta.at(var.self).decoration.alias = meta.at(type.self).decoration.alias; @@ -1112,7 +1112,7 @@ void Compiler::parse(const Instruction &instruction) { uint32_t cap = ops[0]; if (cap == CapabilityKernel) - throw CompilerError("Kernel capability not supported."); + SPIRV_CROSS_THROW("Kernel capability not supported."); break; } @@ -1123,7 +1123,7 @@ void Compiler::parse(const Instruction &instruction) if (ext == "GLSL.std.450") set(id, SPIRExtension::GLSL); else - throw CompilerError("Only GLSL.std.450 extension interface supported."); + SPIRV_CROSS_THROW("Only GLSL.std.450 extension interface supported."); break; } @@ -1362,7 +1362,7 @@ void Compiler::parse(const Instruction &instruction) ptrbase = base; if (ptrbase.pointer) - throw CompilerError("Cannot make pointer-to-pointer type."); + SPIRV_CROSS_THROW("Cannot make pointer-to-pointer type."); ptrbase.pointer = true; ptrbase.storage = static_cast(ops[1]); @@ -1425,7 +1425,7 @@ void Compiler::parse(const Instruction &instruction) if (storage == StorageClassFunction) { if (!current_function) - throw CompilerError("No function currently in scope"); + SPIRV_CROSS_THROW("No function currently in scope"); current_function->add_local_variable(id); } else if (storage == StorageClassPrivate || storage == StorageClassWorkgroup || storage == StorageClassOutput) @@ -1460,9 +1460,9 @@ void Compiler::parse(const Instruction &instruction) case OpPhi: { if (!current_function) - throw CompilerError("No function currently in scope"); + SPIRV_CROSS_THROW("No function currently in scope"); if (!current_block) - throw CompilerError("No block currently in scope"); + SPIRV_CROSS_THROW("No block currently in scope"); uint32_t result_type = ops[0]; uint32_t id = ops[1]; @@ -1554,7 +1554,7 @@ void Compiler::parse(const Instruction &instruction) break; default: - throw CompilerError("OpConstantComposite only supports 1, 2, 3 and 4 columns."); + SPIRV_CROSS_THROW("OpConstantComposite only supports 1, 2, 3 and 4 columns."); } } else @@ -1612,7 +1612,7 @@ void Compiler::parse(const Instruction &instruction) break; default: - throw CompilerError("OpConstantComposite only supports 1, 2, 3 and 4 components."); + SPIRV_CROSS_THROW("OpConstantComposite only supports 1, 2, 3 and 4 components."); } } @@ -1629,7 +1629,7 @@ void Compiler::parse(const Instruction &instruction) uint32_t type = ops[3]; if (current_function) - throw CompilerError("Must end a function before starting a new one!"); + SPIRV_CROSS_THROW("Must end a function before starting a new one!"); current_function = &set(id, res, type); break; @@ -1641,7 +1641,7 @@ void Compiler::parse(const Instruction &instruction) uint32_t id = ops[1]; if (!current_function) - throw CompilerError("Must be in a function!"); + SPIRV_CROSS_THROW("Must be in a function!"); current_function->add_parameter(type, id); set(id, type, StorageClassFunction); @@ -1653,7 +1653,7 @@ void Compiler::parse(const Instruction &instruction) if (current_block) { // Very specific error message, but seems to come up quite often. - throw CompilerError( + SPIRV_CROSS_THROW( "Cannot end a function before ending the current block.\n" "Likely cause: If this SPIR-V was created from glslang HLSL, make sure the entry point is valid."); } @@ -1666,7 +1666,7 @@ void Compiler::parse(const Instruction &instruction) { // OpLabel always starts a block. if (!current_function) - throw CompilerError("Blocks cannot exist outside functions!"); + SPIRV_CROSS_THROW("Blocks cannot exist outside functions!"); uint32_t id = ops[0]; @@ -1675,7 +1675,7 @@ void Compiler::parse(const Instruction &instruction) current_function->entry_block = id; if (current_block) - throw CompilerError("Cannot start a block before ending the current block."); + SPIRV_CROSS_THROW("Cannot start a block before ending the current block."); current_block = &set(id); break; @@ -1685,7 +1685,7 @@ void Compiler::parse(const Instruction &instruction) case OpBranch: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); uint32_t target = ops[0]; current_block->terminator = SPIRBlock::Direct; @@ -1697,7 +1697,7 @@ void Compiler::parse(const Instruction &instruction) case OpBranchConditional: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); current_block->condition = ops[0]; current_block->true_block = ops[1]; @@ -1711,10 +1711,10 @@ void Compiler::parse(const Instruction &instruction) case OpSwitch: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); if (current_block->merge == SPIRBlock::MergeNone) - throw CompilerError("Switch statement is not structured"); + SPIRV_CROSS_THROW("Switch statement is not structured"); current_block->terminator = SPIRBlock::MultiSelect; @@ -1734,7 +1734,7 @@ void Compiler::parse(const Instruction &instruction) case OpKill: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); current_block->terminator = SPIRBlock::Kill; current_block = nullptr; break; @@ -1743,7 +1743,7 @@ void Compiler::parse(const Instruction &instruction) case OpReturn: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); current_block->terminator = SPIRBlock::Return; current_block = nullptr; break; @@ -1752,7 +1752,7 @@ void Compiler::parse(const Instruction &instruction) case OpReturnValue: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); current_block->terminator = SPIRBlock::Return; current_block->return_value = ops[0]; current_block = nullptr; @@ -1762,7 +1762,7 @@ void Compiler::parse(const Instruction &instruction) case OpUnreachable: { if (!current_block) - throw CompilerError("Trying to end a non-existing block."); + SPIRV_CROSS_THROW("Trying to end a non-existing block."); current_block->terminator = SPIRBlock::Unreachable; current_block = nullptr; break; @@ -1771,7 +1771,7 @@ void Compiler::parse(const Instruction &instruction) case OpSelectionMerge: { if (!current_block) - throw CompilerError("Trying to modify a non-existing block."); + SPIRV_CROSS_THROW("Trying to modify a non-existing block."); current_block->next_block = ops[0]; current_block->merge = SPIRBlock::MergeSelection; @@ -1782,7 +1782,7 @@ void Compiler::parse(const Instruction &instruction) case OpLoopMerge: { if (!current_block) - throw CompilerError("Trying to modify a non-existing block."); + SPIRV_CROSS_THROW("Trying to modify a non-existing block."); current_block->merge_block = ops[0]; current_block->continue_block = ops[1]; @@ -1802,7 +1802,7 @@ void Compiler::parse(const Instruction &instruction) case OpSpecConstantOp: { if (length < 3) - throw CompilerError("OpSpecConstantOp not enough arguments."); + SPIRV_CROSS_THROW("OpSpecConstantOp not enough arguments."); uint32_t result_type = ops[0]; uint32_t id = ops[1]; @@ -1816,7 +1816,7 @@ void Compiler::parse(const Instruction &instruction) default: { if (!current_block) - throw CompilerError("Currently no block to insert opcode."); + SPIRV_CROSS_THROW("Currently no block to insert opcode."); current_block->ops.push_back(instruction); break; @@ -2040,7 +2040,7 @@ uint32_t Compiler::type_struct_member_offset(const SPIRType &type, uint32_t inde if (dec.decoration_flags & (1ull << DecorationOffset)) return dec.offset; else - throw CompilerError("Struct member does not have Offset set."); + SPIRV_CROSS_THROW("Struct member does not have Offset set."); } uint32_t Compiler::type_struct_member_array_stride(const SPIRType &type, uint32_t index) const @@ -2051,7 +2051,7 @@ uint32_t Compiler::type_struct_member_array_stride(const SPIRType &type, uint32_ if (dec.decoration_flags & (1ull << DecorationArrayStride)) return dec.array_stride; else - throw CompilerError("Struct member does not have ArrayStride set."); + SPIRV_CROSS_THROW("Struct member does not have ArrayStride set."); } size_t Compiler::get_declared_struct_size(const SPIRType &type) const @@ -2078,7 +2078,7 @@ size_t Compiler::get_declared_struct_member_size(const SPIRType &struct_type, ui case SPIRType::Image: case SPIRType::SampledImage: case SPIRType::Sampler: - throw CompilerError("Querying size for object with opaque size.\n"); + SPIRV_CROSS_THROW("Querying size for object with opaque size.\n"); default: break; @@ -2357,7 +2357,7 @@ SPIREntryPoint &Compiler::get_entry_point(const std::string &name) [&](const std::pair &entry) -> bool { return entry.second.name == name; }); if (itr == end(entry_points)) - throw CompilerError("Entry point does not exist."); + SPIRV_CROSS_THROW("Entry point does not exist."); return itr->second; } @@ -2369,7 +2369,7 @@ const SPIREntryPoint &Compiler::get_entry_point(const std::string &name) const [&](const std::pair &entry) -> bool { return entry.second.name == name; }); if (itr == end(entry_points)) - throw CompilerError("Entry point does not exist."); + SPIRV_CROSS_THROW("Entry point does not exist."); return itr->second; } @@ -2388,7 +2388,7 @@ bool Compiler::interface_variable_exists_in_entry_point(uint32_t id) const { auto &var = get(id); if (var.storage != StorageClassInput && var.storage != StorageClassOutput) - throw CompilerError("Only Input and Output variables are part of a shader linking interface."); + SPIRV_CROSS_THROW("Only Input and Output variables are part of a shader linking interface."); // This is to avoid potential problems with very old glslang versions which did // not emit input/output interfaces properly. @@ -2613,11 +2613,11 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1; bool separate_sampler = type.basetype == SPIRType::Sampler; if (separate_image) - throw CompilerError( + SPIRV_CROSS_THROW( "Attempting to use arrays of separate images. This is not possible to statically remap to plain GLSL."); if (separate_sampler) - throw CompilerError("Attempting to use arrays of separate samplers. This is not possible to statically " - "remap to plain GLSL."); + SPIRV_CROSS_THROW("Attempting to use arrays of separate samplers. This is not possible to statically " + "remap to plain GLSL."); return true; } diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 36c5bc5..5ba6258 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -327,7 +327,7 @@ protected: return nullptr; if (instr.offset + instr.length > spirv.size()) - throw CompilerError("Compiler::stream() out of range."); + SPIRV_CROSS_THROW("Compiler::stream() out of range."); return &spirv[instr.offset]; } std::vector spirv; diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 360c415..3e501d1 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -184,7 +184,7 @@ void CompilerGLSL::remap_pls_variables() } if (var.storage != StorageClassInput && !input_is_target) - throw CompilerError("Can only use in and target variables for PLS inputs."); + SPIRV_CROSS_THROW("Can only use in and target variables for PLS inputs."); var.remapped_variable = true; } @@ -192,7 +192,7 @@ void CompilerGLSL::remap_pls_variables() { auto &var = get(output.id); if (var.storage != StorageClassOutput) - throw CompilerError("Can only use out variables for PLS outputs."); + SPIRV_CROSS_THROW("Can only use out variables for PLS outputs."); var.remapped_variable = true; } } @@ -207,7 +207,7 @@ void CompilerGLSL::find_static_extensions() if (type.basetype == SPIRType::Double) { if (options.es) - throw CompilerError("FP64 not supported in ES profile."); + SPIRV_CROSS_THROW("FP64 not supported in ES profile."); if (!options.es && options.version < 400) require_extension("GL_ARB_gpu_shader_fp64"); } @@ -215,7 +215,7 @@ void CompilerGLSL::find_static_extensions() if (type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64) { if (options.es) - throw CompilerError("64-bit integers not supported in ES profile."); + SPIRV_CROSS_THROW("64-bit integers not supported in ES profile."); if (!options.es) require_extension("GL_ARB_gpu_shader_int64"); } @@ -229,7 +229,7 @@ void CompilerGLSL::find_static_extensions() if (!options.es && options.version < 430) require_extension("GL_ARB_compute_shader"); if (options.es && options.version < 310) - throw CompilerError("At least ESSL 3.10 required for compute shaders."); + SPIRV_CROSS_THROW("At least ESSL 3.10 required for compute shaders."); break; case ExecutionModelGeometry: @@ -271,7 +271,7 @@ string CompilerGLSL::compile() do { if (pass_count >= 3) - throw CompilerError("Over 3 compilation loops detected. Must be a bug!"); + SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!"); reset(); @@ -561,7 +561,7 @@ const char *CompilerGLSL::format_to_glsl(spv::ImageFormat format) { auto check_desktop = [this] { if (options.es) - throw CompilerError("Attempting to use image format not supported in ES profile."); + SPIRV_CROSS_THROW("Attempting to use image format not supported in ES profile."); }; switch (format) @@ -747,7 +747,7 @@ uint32_t CompilerGLSL::type_to_std430_alignment(const SPIRType &type, uint64_t f // Rule 8 implied. } - throw CompilerError("Did not find suitable std430 rule for type. Bogus decorations?"); + SPIRV_CROSS_THROW("Did not find suitable std430 rule for type. Bogus decorations?"); } uint32_t CompilerGLSL::type_to_std430_array_stride(const SPIRType &type, uint64_t flags) @@ -978,7 +978,7 @@ void CompilerGLSL::emit_push_constant_block_glsl(const SPIRVariable &var) #if 0 if (flags & ((1ull << DecorationBinding) | (1ull << DecorationDescriptorSet))) - throw CompilerError("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. " + SPIRV_CROSS_THROW("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. " "Remap to location with reflection API first or disable these decorations."); #endif @@ -1096,7 +1096,7 @@ void CompilerGLSL::emit_uniform(const SPIRVariable &var) if (!options.es && options.version < 420) require_extension("GL_ARB_shader_image_load_store"); else if (options.es && options.version < 310) - throw CompilerError("At least ESSL 3.10 required for shader image load store."); + SPIRV_CROSS_THROW("At least ESSL 3.10 required for shader image load store."); } add_resource_name(var.self); @@ -1182,14 +1182,14 @@ void CompilerGLSL::replace_fragment_output(SPIRVariable &var) // FIXME: This seems like an extremely odd-ball case, so it's probably fine to leave it like this for now. m.alias = "gl_FragData"; if (location != 0) - throw CompilerError("Arrayed output variable used, but location is not 0. " - "This is unimplemented in SPIRV-Cross."); + SPIRV_CROSS_THROW("Arrayed output variable used, but location is not 0. " + "This is unimplemented in SPIRV-Cross."); if (is_legacy_es()) require_extension("GL_EXT_draw_buffers"); } else - throw CompilerError("Array-of-array output variable used. This cannot be implemented in legacy GLSL."); + SPIRV_CROSS_THROW("Array-of-array output variable used. This cannot be implemented in legacy GLSL."); var.compat_builtin = true; // We don't want to declare this variable, but use the name as-is. } @@ -1234,13 +1234,13 @@ void CompilerGLSL::emit_pls() { auto &execution = get_entry_point(); if (execution.model != ExecutionModelFragment) - throw CompilerError("Pixel local storage only supported in fragment shaders."); + SPIRV_CROSS_THROW("Pixel local storage only supported in fragment shaders."); if (!options.es) - throw CompilerError("Pixel local storage only supported in OpenGL ES."); + SPIRV_CROSS_THROW("Pixel local storage only supported in OpenGL ES."); if (options.version < 300) - throw CompilerError("Pixel local storage only supported in ESSL 3.0 and above."); + SPIRV_CROSS_THROW("Pixel local storage only supported in ESSL 3.0 and above."); if (!pls_inputs.empty()) { @@ -1651,7 +1651,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) case OpSelect: { if (cop.arguments.size() < 3) - throw CompilerError("Not enough arguments to OpSpecConstantOp."); + SPIRV_CROSS_THROW("Not enough arguments to OpSpecConstantOp."); // This one is pretty annoying. It's triggered from // uint(bool), int(bool) from spec constants. @@ -1660,7 +1660,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) // If we cannot, fail. if (!to_trivial_mix_op(type, op, cop.arguments[2], cop.arguments[1], cop.arguments[0])) { - throw CompilerError( + SPIRV_CROSS_THROW( "Cannot implement specialization constant op OpSelect. " "Need trivial select implementation which can be resolved to a simple cast from boolean."); } @@ -1669,7 +1669,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) default: // Some opcodes are unimplemented here, these are currently not possible to test from glslang. - throw CompilerError("Unimplemented spec constant op."); + SPIRV_CROSS_THROW("Unimplemented spec constant op."); } SPIRType::BaseType input_type; @@ -1692,7 +1692,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) if (binary) { if (cop.arguments.size() < 2) - throw CompilerError("Not enough arguments to OpSpecConstantOp."); + SPIRV_CROSS_THROW("Not enough arguments to OpSpecConstantOp."); string cast_op0; string cast_op1; @@ -1714,7 +1714,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) else if (unary) { if (cop.arguments.size() < 1) - throw CompilerError("Not enough arguments to OpSpecConstantOp."); + SPIRV_CROSS_THROW("Not enough arguments to OpSpecConstantOp."); // Auto-bitcast to result type as needed. // Works around various casting scenarios in glslang as there is no OpBitcast for specialization constants. @@ -1723,7 +1723,7 @@ string CompilerGLSL::constant_op_expression(const SPIRConstantOp &cop) else { if (cop.arguments.size() < 1) - throw CompilerError("Not enough arguments to OpSpecConstantOp."); + SPIRV_CROSS_THROW("Not enough arguments to OpSpecConstantOp."); return join(op, "(", to_expression(cop.arguments[0]), ")"); } } @@ -1939,7 +1939,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t break; default: - throw CompilerError("Invalid constant expression basetype."); + SPIRV_CROSS_THROW("Invalid constant expression basetype."); } if (c.vector_size() > 1) @@ -2206,7 +2206,9 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp else if (op == "textureProjLod") return join("texture", type, is_legacy_es() ? "ProjLodEXT" : "ProjLod"); else - throw CompilerError(join("Unsupported legacy texture op: ", op)); + { + SPIRV_CROSS_THROW(join("Unsupported legacy texture op: ", op)); + } } bool CompilerGLSL::to_trivial_mix_op(const SPIRType &type, string &op, uint32_t left, uint32_t right, uint32_t lerp) @@ -2351,7 +2353,7 @@ string CompilerGLSL::to_combined_image_sampler(uint32_t image_id, uint32_t samp_ return to_expression(itr->id); else { - throw CompilerError( + SPIRV_CROSS_THROW( "Cannot find mapping for combined sampler parameter, was build_combined_image_samplers() used " "before compile() was called?"); } @@ -2368,8 +2370,8 @@ string CompilerGLSL::to_combined_image_sampler(uint32_t image_id, uint32_t samp_ return to_expression(itr->combined_id); else { - throw CompilerError("Cannot find mapping for combined sampler, was build_combined_image_samplers() used " - "before compile() was called?"); + SPIRV_CROSS_THROW("Cannot find mapping for combined sampler, was build_combined_image_samplers() used " + "before compile() was called?"); } } } @@ -2392,7 +2394,7 @@ void CompilerGLSL::emit_texture_op(const Instruction &i) uint32_t length = i.length; if (i.offset + length > spirv.size()) - throw CompilerError("Compiler::parse() opcode out of range."); + SPIRV_CROSS_THROW("Compiler::parse() opcode out of range."); uint32_t result_type = ops[0]; uint32_t id = ops[1]; @@ -2671,7 +2673,7 @@ void CompilerGLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop, if ((options.es && options.version >= 300) || (!options.es && options.version >= 130)) emit_unary_func_op(result_type, id, args[0], "roundEven"); else - throw CompilerError("roundEven supported only in ESSL 300 and GLSL 130 and up."); + SPIRV_CROSS_THROW("roundEven supported only in ESSL 300 and GLSL 130 and up."); break; case GLSLstd450Trunc: @@ -2957,12 +2959,12 @@ string CompilerGLSL::builtin_to_glsl(BuiltIn builtin) return "gl_PointSize"; case BuiltInVertexId: if (options.vulkan_semantics) - throw CompilerError( + SPIRV_CROSS_THROW( "Cannot implement gl_VertexID in Vulkan GLSL. This shader was created with GL semantics."); return "gl_VertexID"; case BuiltInInstanceId: if (options.vulkan_semantics) - throw CompilerError( + SPIRV_CROSS_THROW( "Cannot implement gl_InstanceID in Vulkan GLSL. This shader was created with GL semantics."); return "gl_InstanceID"; case BuiltInVertexIndex: @@ -3025,7 +3027,7 @@ const char *CompilerGLSL::index_to_swizzle(uint32_t index) case 3: return "w"; default: - throw CompilerError("Swizzle index out of range"); + SPIRV_CROSS_THROW("Swizzle index out of range"); } } @@ -3074,7 +3076,7 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32 index = get(index).scalar(); if (index >= type->member_types.size()) - throw CompilerError("Member index is out of bounds!"); + SPIRV_CROSS_THROW("Member index is out of bounds!"); BuiltIn builtin; if (is_member_builtin(*type, index, &builtin)) @@ -3148,7 +3150,7 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32 temp.vecsize = 1; } else - throw CompilerError("Cannot subdivide a scalar value!"); + SPIRV_CROSS_THROW("Cannot subdivide a scalar value!"); } return expr; @@ -3656,7 +3658,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) length -= 2; if (!length) - throw CompilerError("Invalid input to OpCompositeConstruct."); + SPIRV_CROSS_THROW("Invalid input to OpCompositeConstruct."); bool forward = true; for (uint32_t i = 0; i < length; i++) @@ -4233,7 +4235,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) break; } default: - throw CompilerError("Illegal argument to OpQuantizeToF16."); + SPIRV_CROSS_THROW("Illegal argument to OpQuantizeToF16."); } emit_op(result_type, id, op, should_forward(arg)); @@ -4460,7 +4462,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) BFOP(textureQueryLOD); } else if (options.es) - throw CompilerError("textureQueryLod not supported in ES profile."); + SPIRV_CROSS_THROW("textureQueryLod not supported in ES profile."); else BFOP(textureQueryLod); break; @@ -4471,7 +4473,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) if (!options.es && options.version < 430) require_extension("GL_ARB_texture_query_levels"); if (options.es) - throw CompilerError("textureQueryLevels not supported in ES profile."); + SPIRV_CROSS_THROW("textureQueryLevels not supported in ES profile."); UFOP(textureQueryLevels); break; } @@ -4480,7 +4482,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { auto *var = maybe_get_backing_variable(ops[2]); if (!var) - throw CompilerError( + SPIRV_CROSS_THROW( "Bug. OpImageQuerySamples must have a backing variable so we know if the image is sampled or not."); auto &type = get(var->basetype); @@ -4531,7 +4533,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) if (var && var->remapped_variable) // Remapped input, just read as-is without any op-code { if (type.image.ms) - throw CompilerError("Trying to remap multisampled image to variable, this is not possible."); + SPIRV_CROSS_THROW("Trying to remap multisampled image to variable, this is not possible."); auto itr = find_if(begin(pls_inputs), end(pls_inputs), [var](const PlsRemap &pls) { return pls.id == var->self; }); @@ -4541,7 +4543,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) // For non-PLS inputs, we rely on subpass type remapping information to get it right // since ImageRead always returns 4-component vectors and the backing type is opaque. if (!var->remapped_components) - throw CompilerError("subpassInput was remapped, but remap_components is not set correctly."); + SPIRV_CROSS_THROW("subpassInput was remapped, but remap_components is not set correctly."); imgexpr = remap_swizzle(result_type, var->remapped_components, ops[2]); } else @@ -4562,7 +4564,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { uint32_t operands = ops[4]; if (operands != ImageOperandsSampleMask || length != 6) - throw CompilerError( + SPIRV_CROSS_THROW( "Multisampled image used in OpImageRead, but unexpected operand mask was used."); uint32_t samples = ops[5]; @@ -4577,7 +4579,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { uint32_t operands = ops[4]; if (operands != ImageOperandsSampleMask || length != 6) - throw CompilerError( + SPIRV_CROSS_THROW( "Multisampled image used in OpImageRead, but unexpected operand mask was used."); uint32_t samples = ops[5]; @@ -4599,8 +4601,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { uint32_t operands = ops[4]; if (operands != ImageOperandsSampleMask || length != 6) - throw CompilerError( - "Multisampled image used in OpImageRead, but unexpected operand mask was used."); + SPIRV_CROSS_THROW("Multisampled image used in OpImageRead, but unexpected operand mask was used."); uint32_t samples = ops[5]; imgexpr = join("imageLoad(", to_expression(ops[2]), ", ", to_expression(ops[3]), ", ", @@ -4660,7 +4661,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { uint32_t operands = ops[3]; if (operands != ImageOperandsSampleMask || length != 5) - throw CompilerError("Multisampled image used in OpImageWrite, but unexpected operand mask was used."); + SPIRV_CROSS_THROW("Multisampled image used in OpImageWrite, but unexpected operand mask was used."); uint32_t samples = ops[4]; statement("imageStore(", to_expression(ops[0]), ", ", to_expression(ops[1]), ", ", to_expression(samples), ", ", to_expression(ops[2]), ");"); @@ -4686,7 +4687,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) emit_op(result_type, id, join("imageSize(", to_expression(ops[2]), ")"), true); } else - throw CompilerError("Invalid type for OpImageQuerySize."); + SPIRV_CROSS_THROW("Invalid type for OpImageQuerySize."); break; } @@ -4801,7 +4802,7 @@ bool CompilerGLSL::is_non_native_row_major_matrix(uint32_t id) // swaps matrix elements while retaining the original dimensional form of the matrix. const auto type = expression_type(id); if (type.columns != type.vecsize) - throw CompilerError("Row-major matrices must be square on this platform."); + SPIRV_CROSS_THROW("Row-major matrices must be square on this platform."); return true; } @@ -4822,7 +4823,7 @@ bool CompilerGLSL::member_is_non_native_row_major_matrix(const SPIRType &type, u // swaps matrix elements while retaining the original dimensional form of the matrix. const auto mbr_type = get(type.member_types[index]); if (mbr_type.columns != mbr_type.vecsize) - throw CompilerError("Row-major matrices must be square on this platform."); + SPIRV_CROSS_THROW("Row-major matrices must be square on this platform."); return true; } @@ -4989,7 +4990,7 @@ uint32_t CompilerGLSL::to_array_size_literal(const SPIRType &type, uint32_t inde assert(type.array.size() == type.array_size_literal.size()); if (!type.array_size_literal[index]) - throw CompilerError("The array size is not a literal, but a specialization constant or spec constant op."); + SPIRV_CROSS_THROW("The array size is not a literal, but a specialization constant or spec constant op."); return type.array[index]; } @@ -5086,7 +5087,7 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type) res += "2D"; break; default: - throw CompilerError("Only 1D, 2D, 3D, Buffer, InputTarget and Cube textures supported."); + SPIRV_CROSS_THROW("Only 1D, 2D, 3D, Buffer, InputTarget and Cube textures supported."); } if (type.image.ms) @@ -5746,7 +5747,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method break; default: - throw CompilerError("For/while loop detected, but need while/for loop semantics."); + SPIRV_CROSS_THROW("For/while loop detected, but need while/for loop semantics."); } begin_scope(); @@ -5793,7 +5794,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method break; default: - throw CompilerError("For/while loop detected, but need while/for loop semantics."); + SPIRV_CROSS_THROW("For/while loop detected, but need while/for loop semantics."); } begin_scope(); @@ -5959,7 +5960,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) statement("default:"); begin_scope(); if (is_break(block.default_block)) - throw CompilerError("Cannot break; out of a switch statement and out of a loop at the same time ..."); + 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(); } @@ -6000,7 +6001,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) break; default: - throw CompilerError("Unimplemented block terminator."); + SPIRV_CROSS_THROW("Unimplemented block terminator."); } if (block.next_block && emit_next_block) @@ -6046,7 +6047,7 @@ void CompilerGLSL::begin_scope() void CompilerGLSL::end_scope() { if (!indent) - throw CompilerError("Popping empty indent stack."); + SPIRV_CROSS_THROW("Popping empty indent stack."); indent--; statement("}"); } @@ -6054,7 +6055,7 @@ void CompilerGLSL::end_scope() void CompilerGLSL::end_scope_decl() { if (!indent) - throw CompilerError("Popping empty indent stack."); + SPIRV_CROSS_THROW("Popping empty indent stack."); indent--; statement("};"); } @@ -6062,7 +6063,7 @@ void CompilerGLSL::end_scope_decl() void CompilerGLSL::end_scope_decl(const string &decl) { if (!indent) - throw CompilerError("Popping empty indent stack."); + SPIRV_CROSS_THROW("Popping empty indent stack."); indent--; statement("} ", decl, ";"); } @@ -6082,10 +6083,10 @@ void CompilerGLSL::check_function_call_constraints(const uint32_t *args, uint32_ auto &type = get(var->basetype); if (type.basetype == SPIRType::Image && type.image.dim == DimSubpassData) { - throw CompilerError("Tried passing a remapped subpassInput variable to a function. " - "This will not work correctly because type-remapping information is lost. " - "To workaround, please consider not passing the subpass input as a function parameter, " - "or use in/out variables instead which do not need type remapping information."); + SPIRV_CROSS_THROW("Tried passing a remapped subpassInput variable to a function. " + "This will not work correctly because type-remapping information is lost. " + "To workaround, please consider not passing the subpass input as a function parameter, " + "or use in/out variables instead which do not need type remapping information."); } } } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 6bcf61f..8ab5b39 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -70,7 +70,7 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector *p_ do { if (pass_count >= 3) - throw CompilerError("Over 3 compilation loops detected. Must be a bug!"); + SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!"); reset(); @@ -688,7 +688,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) } } else - throw CompilerError("Invalid type for OpImageQuerySize."); + SPIRV_CROSS_THROW("Invalid type for OpImageQuerySize."); break; } @@ -819,7 +819,7 @@ void CompilerMSL::emit_texture_op(const Instruction &i) uint32_t length = i.length; if (i.offset + length > spirv.size()) - throw CompilerError("Compiler::compile() opcode out of range."); + SPIRV_CROSS_THROW("Compiler::compile() opcode out of range."); uint32_t result_type = ops[0]; uint32_t id = ops[1]; @@ -1938,7 +1938,7 @@ size_t CompilerMSL::get_declared_type_size(const SPIRType &type, uint64_t dec_ma case SPIRType::Image: case SPIRType::SampledImage: case SPIRType::Sampler: - throw CompilerError("Querying size of object with opaque size."); + SPIRV_CROSS_THROW("Querying size of object with opaque size."); default: break; } @@ -1972,7 +1972,7 @@ size_t CompilerMSL::get_declared_type_size(const SPIRType &type, uint64_t dec_ma return dec.array_stride * to_array_size_literal(type, uint32_t(type.array.size()) - 1); else { - throw CompilerError("Type does not have ArrayStride set."); + SPIRV_CROSS_THROW("Type does not have ArrayStride set."); } } }