diff --git a/.travis.yml b/.travis.yml index 38b9a383..f90439ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ dist: trusty # We check out glslang at a specific revision to avoid test output mismatches env: - - GLSLANG_REV=e4e8f7b7a31a751be285b64741465b769f5f146f + - GLSLANG_REV=19ea56899cdcab0f480d257fcea100ad2160e833 before_script: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3; fi @@ -25,5 +25,5 @@ script: - make -j2 - PATH=./glslang/StandAlone:./SPIRV-Tools/tools:$PATH - ./test_shaders.py shaders - - ./test_shaders.py --metal shaders-msl + - ./test_shaders.py --msl shaders-msl - ./test_shaders.py --hlsl shaders-hlsl diff --git a/reference/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag b/reference/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag new file mode 100644 index 00000000..a4cf0783 --- /dev/null +++ b/reference/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag @@ -0,0 +1,20 @@ +#version 450 + +layout(rgba32f) uniform writeonly imageBuffer RWTex; +uniform samplerBuffer Tex; + +layout(location = 0) out vec4 _entryPointOutput; + +vec4 _main() +{ + vec4 storeTemp = vec4(1.0, 2.0, 3.0, 4.0); + imageStore(RWTex, 20, storeTemp); + return texelFetch(Tex, 10); +} + +void main() +{ + vec4 _28 = _main(); + _entryPointOutput = _28; +} + diff --git a/reference/shaders/asm/vert/empty-io.asm.vert b/reference/shaders/asm/vert/empty-io.asm.vert new file mode 100644 index 00000000..e1a56d9d --- /dev/null +++ b/reference/shaders/asm/vert/empty-io.asm.vert @@ -0,0 +1,29 @@ +#version 450 + +struct VSInput +{ + vec4 position; +}; + +struct VSOutput +{ + vec4 position; +}; + +layout(location = 0) in vec4 position; + +VSOutput _main(VSInput _input) +{ + VSOutput _out; + _out.position = _input.position; + return _out; +} + +void main() +{ + VSInput _input; + _input.position = position; + VSInput param = _input; + gl_Position = _main(param).position; +} + diff --git a/reference/shaders/comp/bitfield.comp b/reference/shaders/comp/bitfield.comp new file mode 100644 index 00000000..49bbddb0 --- /dev/null +++ b/reference/shaders/comp/bitfield.comp @@ -0,0 +1,19 @@ +#version 310 es +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +void main() +{ + int signed_value = 0; + uint unsigned_value = 0u; + int s = bitfieldExtract(signed_value, 5, 20); + uint u = bitfieldExtract(unsigned_value, 6, 21); + s = bitfieldInsert(s, 40, 5, 4); + u = bitfieldInsert(u, 60u, 5, 4); + u = bitfieldReverse(u); + s = bitfieldReverse(s); + int v0 = bitCount(u); + int v1 = bitCount(s); + int v2 = findMSB(u); + int v3 = findLSB(s); +} + diff --git a/reference/shaders/comp/cfg-preserve-parameter.comp b/reference/shaders/comp/cfg-preserve-parameter.comp new file mode 100644 index 00000000..72bde44a --- /dev/null +++ b/reference/shaders/comp/cfg-preserve-parameter.comp @@ -0,0 +1,74 @@ +#version 310 es +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +void out_test_0(int cond, out int i) +{ + if (cond == 0) + { + i = 40; + } + else + { + i = 60; + } +} + +void out_test_1(int cond, out int i) +{ + switch (cond) + { + case 40: + { + i = 40; + break; + } + default: + { + i = 70; + break; + } + } +} + +void inout_test_0(int cond, inout int i) +{ + if (cond == 0) + { + i = 40; + } +} + +void inout_test_1(int cond, inout int i) +{ + switch (cond) + { + case 40: + { + i = 40; + break; + } + } +} + +void main() +{ + int cond = 40; + int i = 50; + int param = cond; + int param_1 = i; + out_test_0(param, param_1); + i = param_1; + int param_2 = cond; + int param_3 = i; + out_test_1(param_2, param_3); + i = param_3; + int param_4 = cond; + int param_5 = i; + inout_test_0(param_4, param_5); + i = param_5; + int param_6 = cond; + int param_7 = i; + inout_test_1(param_6, param_7); + i = param_7; +} + diff --git a/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag b/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag new file mode 100644 index 00000000..9c08fc28 --- /dev/null +++ b/shaders/asm/frag/sampler-buffer-without-sampler.asm.frag @@ -0,0 +1,59 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 1 +; Bound: 36 +; Schema: 0 + OpCapability Shader + OpCapability SampledBuffer + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %_entryPointOutput + OpExecutionMode %main OriginUpperLeft + OpName %main "main" + OpName %_main_ "@main(" + OpName %storeTemp "storeTemp" + OpName %RWTex "RWTex" + OpName %Tex "Tex" + OpName %_entryPointOutput "@entryPointOutput" + OpDecorate %RWTex DescriptorSet 0 + OpDecorate %Tex DescriptorSet 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 + %13 = OpConstant %float 1 + %14 = OpConstant %float 2 + %15 = OpConstant %float 3 + %16 = OpConstant %float 4 + %17 = OpConstantComposite %v4float %13 %14 %15 %16 + %18 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f +%_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 + %RWTex = OpVariable %_ptr_UniformConstant_18 UniformConstant + %int = OpTypeInt 32 1 + %23 = OpConstant %int 20 + %25 = OpTypeImage %float Buffer 0 0 0 1 Rgba32f +%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 + %Tex = OpVariable %_ptr_UniformConstant_25 UniformConstant + %29 = OpConstant %int 10 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%_entryPointOutput = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %35 = OpFunctionCall %v4float %_main_ + OpStore %_entryPointOutput %35 + OpReturn + OpFunctionEnd + %_main_ = OpFunction %v4float None %8 + %10 = OpLabel + %storeTemp = OpVariable %_ptr_Function_v4float Function + OpStore %storeTemp %17 + %21 = OpLoad %18 %RWTex + %24 = OpLoad %v4float %storeTemp + OpImageWrite %21 %23 %24 + %28 = OpLoad %25 %Tex + %30 = OpImageFetch %v4float %28 %29 + OpReturnValue %30 + OpFunctionEnd diff --git a/shaders/asm/vert/empty-io.asm.vert b/shaders/asm/vert/empty-io.asm.vert new file mode 100644 index 00000000..0ba6cb79 --- /dev/null +++ b/shaders/asm/vert/empty-io.asm.vert @@ -0,0 +1,70 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 1 +; Bound: 40 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %position %_entryPointOutput_position %_entryPointOutput + OpName %main "main" + OpName %VSInput "VSInput" + OpMemberName %VSInput 0 "position" + OpName %VSOutput "VSOutput" + OpMemberName %VSOutput 0 "position" + OpName %_main_struct_VSInput_vf41_ "@main(struct-VSInput-vf41;" + OpName %_input "_input" + OpName %_out "_out" + OpName %_input_0 "_input" + OpName %position "position" + OpName %_entryPointOutput_position "@entryPointOutput_position" + OpName %param "param" + OpName %VSOutput_0 "VSOutput" + OpName %_entryPointOutput "@entryPointOutput" + OpDecorate %position Location 0 + OpDecorate %_entryPointOutput_position BuiltIn Position + OpDecorate %_entryPointOutput Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %VSInput = OpTypeStruct %v4float +%_ptr_Function_VSInput = OpTypePointer Function %VSInput + %VSOutput = OpTypeStruct %v4float + %11 = OpTypeFunction %VSOutput %_ptr_Function_VSInput +%_ptr_Function_VSOutput = OpTypePointer Function %VSOutput + %int = OpTypeInt 32 1 + %18 = OpConstant %int 0 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%_ptr_Input_v4float = OpTypePointer Input %v4float + %position = OpVariable %_ptr_Input_v4float Input +%_ptr_Output_v4float = OpTypePointer Output %v4float +%_entryPointOutput_position = OpVariable %_ptr_Output_v4float Output + %VSOutput_0 = OpTypeStruct +%_ptr_Output_VSOutput_0 = OpTypePointer Output %VSOutput_0 +%_entryPointOutput = OpVariable %_ptr_Output_VSOutput_0 Output + %main = OpFunction %void None %3 + %5 = OpLabel + %_input_0 = OpVariable %_ptr_Function_VSInput Function + %param = OpVariable %_ptr_Function_VSInput Function + %29 = OpLoad %v4float %position + %30 = OpAccessChain %_ptr_Function_v4float %_input_0 %18 + OpStore %30 %29 + %34 = OpLoad %VSInput %_input_0 + OpStore %param %34 + %35 = OpFunctionCall %VSOutput %_main_struct_VSInput_vf41_ %param + %36 = OpCompositeExtract %v4float %35 0 + OpStore %_entryPointOutput_position %36 + OpReturn + OpFunctionEnd +%_main_struct_VSInput_vf41_ = OpFunction %VSOutput None %11 + %_input = OpFunctionParameter %_ptr_Function_VSInput + %14 = OpLabel + %_out = OpVariable %_ptr_Function_VSOutput Function + %20 = OpAccessChain %_ptr_Function_v4float %_input %18 + %21 = OpLoad %v4float %20 + %22 = OpAccessChain %_ptr_Function_v4float %_out %18 + OpStore %22 %21 + %23 = OpLoad %VSOutput %_out + OpReturnValue %23 + OpFunctionEnd diff --git a/shaders/comp/bitfield.comp b/shaders/comp/bitfield.comp new file mode 100644 index 00000000..d75b556b --- /dev/null +++ b/shaders/comp/bitfield.comp @@ -0,0 +1,21 @@ +#version 310 es + +void main() +{ + int signed_value = 0; + uint unsigned_value = 0u; + + int s = bitfieldExtract(signed_value, 5, 20); + uint u = bitfieldExtract(unsigned_value, 6, 21); + s = bitfieldInsert(s, 40, 5, 4); + u = bitfieldInsert(u, 60u, 5, 4); + + u = bitfieldReverse(u); + s = bitfieldReverse(s); + + int v0 = bitCount(u); + int v1 = bitCount(s); + + int v2 = findMSB(u); + int v3 = findLSB(s); +} diff --git a/shaders/comp/cfg-preserve-parameter.comp b/shaders/comp/cfg-preserve-parameter.comp new file mode 100644 index 00000000..9ef90920 --- /dev/null +++ b/shaders/comp/cfg-preserve-parameter.comp @@ -0,0 +1,54 @@ +#version 310 es + +// We write in all paths (and no reads), so should just be out. +void out_test_0(int cond, inout int i) +{ + if (cond == 0) + i = 40; + else + i = 60; +} + +// We write in all paths (and no reads), so should just be out. +void out_test_1(int cond, inout int i) +{ + switch (cond) + { + case 40: + i = 40; + break; + + default: + i = 70; + break; + } +} + +// We don't write in all paths, so should be inout. +void inout_test_0(int cond, inout int i) +{ + if (cond == 0) + i = 40; +} + +void inout_test_1(int cond, inout int i) +{ + switch (cond) + { + case 40: + i = 40; + break; + } +} + + +void main() +{ + int cond = 40; + int i = 50; + + out_test_0(cond, i); + out_test_1(cond, i); + inout_test_0(cond, i); + inout_test_1(cond, i); +} diff --git a/spirv_cfg.cpp b/spirv_cfg.cpp index b7abf477..32549edc 100644 --- a/spirv_cfg.cpp +++ b/spirv_cfg.cpp @@ -15,6 +15,7 @@ */ #include "spirv_cfg.hpp" +#include "spirv_cross.hpp" #include #include diff --git a/spirv_cfg.hpp b/spirv_cfg.hpp index 882f7d3d..7e214404 100644 --- a/spirv_cfg.hpp +++ b/spirv_cfg.hpp @@ -17,11 +17,12 @@ #ifndef SPIRV_CROSS_CFG_HPP #define SPIRV_CROSS_CFG_HPP -#include "spirv_cross.hpp" +#include "spirv_common.hpp" #include namespace spirv_cross { +class Compiler; class CFG { public: diff --git a/spirv_common.hpp b/spirv_common.hpp index d7d037fb..79e04702 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -17,11 +17,21 @@ #ifndef SPIRV_CROSS_COMMON_HPP #define SPIRV_CROSS_COMMON_HPP +#include "spirv.hpp" + #include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include namespace spirv_cross { diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 8119c344..84b167b3 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -70,6 +70,12 @@ Compiler::Compiler(vector ir) parse(); } +Compiler::Compiler(const uint32_t *ir, size_t word_count) + : spirv(ir, ir + word_count) +{ + parse(); +} + string Compiler::compile() { // Force a classic "C" locale, reverts when function returns @@ -1405,7 +1411,6 @@ void Compiler::parse(const Instruction &instruction) break; } - // Not really used. case OpTypeSampler: { uint32_t id = ops[0]; @@ -2802,6 +2807,71 @@ const SPIRConstant &Compiler::get_constant(uint32_t id) const return get(id); } +static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set &blocks) +{ + // This block accesses the variable. + if (blocks.find(block) != end(blocks)) + return false; + + // We are at the end of the CFG. + if (cfg.get_succeeding_edges(block).empty()) + return true; + + // If any of our successors have a path to the end, there exists a path from block. + for (auto &succ : cfg.get_succeeding_edges(block)) + if (exists_unaccessed_path_to_return(cfg, succ, blocks)) + return true; + + return false; +} + +void Compiler::analyze_parameter_preservation( + SPIRFunction &entry, const CFG &cfg, const unordered_map> &variable_to_blocks) +{ + for (auto &arg : entry.arguments) + { + // Non-pointers are always inputs. + auto &type = get(arg.type); + if (!type.pointer) + continue; + + // Opaque argument types are always in + bool potential_preserve; + switch (type.basetype) + { + case SPIRType::Sampler: + case SPIRType::Image: + case SPIRType::SampledImage: + case SPIRType::AtomicCounter: + potential_preserve = false; + break; + + default: + potential_preserve = true; + break; + } + + if (!potential_preserve) + continue; + + auto itr = variable_to_blocks.find(arg.id); + if (itr == end(variable_to_blocks)) + { + // Variable is never accessed. + continue; + } + + // If there is a path through the CFG where no block writes to the variable, the variable will be in an undefined state + // when the function returns. We therefore need to implicitly preserve the variable in case there are writers in the function. + // Major case here is if a function is + // void foo(int &var) { if (cond) var = 10; } + // Using read/write counts, we will think it's just an out variable, but it really needs to be inout, + // because if we don't write anything whatever we put into the function must return back to the caller. + if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second)) + arg.read_count++; + } +} + void Compiler::analyze_variable_scope(SPIRFunction &entry) { struct AccessHandler : OpcodeHandler @@ -2971,6 +3041,9 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry) // Compute the control flow graph for this function. CFG cfg(*this, entry); + // Analyze if there are parameters which need to be implicitly preserved with an "in" qualifier. + analyze_parameter_preservation(entry, cfg, handler.accessed_variables_to_block); + unordered_map potential_loop_variables; // For each variable which is statically accessed. diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 26d22ddb..08b052c2 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -18,19 +18,11 @@ #define SPIRV_CROSS_HPP #include "spirv.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - #include "spirv_common.hpp" namespace spirv_cross { +class CFG; struct Resource { // Resources are identified with their SPIR-V ID. @@ -114,6 +106,7 @@ public: // The constructor takes a buffer of SPIR-V words and parses it. Compiler(std::vector ir); + Compiler(const uint32_t *ir, size_t word_count); virtual ~Compiler() = default; @@ -614,6 +607,10 @@ protected: uint64_t active_output_builtins = 0; // Traverses all reachable opcodes and sets active_builtins to a bitmask of all builtin variables which are accessed in the shader. void update_active_builtins(); + + void analyze_parameter_preservation( + SPIRFunction &entry, const CFG &cfg, + const std::unordered_map> &variable_to_blocks); }; } diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 86e63bf3..76010286 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -483,6 +483,11 @@ void CompilerGLSL::emit_header() statement(""); } +bool CompilerGLSL::type_is_empty(const SPIRType &type) +{ + return type.basetype == SPIRType::Struct && type.member_types.empty(); +} + void CompilerGLSL::emit_struct(SPIRType &type) { // Struct types can be stamped out multiple times @@ -492,6 +497,12 @@ void CompilerGLSL::emit_struct(SPIRType &type) if (type.type_alias != 0) return; + // Don't declare empty structs in GLSL, this is not allowed. + // Empty structs is a corner case of HLSL output, and only sensible thing to do is avoiding to declare + // these types. + if (type_is_empty(type)) + return; + add_resource_name(type.self); auto name = type_to_glsl(type); @@ -985,7 +996,8 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var) attr.push_back(ssbo_is_std430_packing(type) ? "std430" : "std140"); // For images, the type itself adds a layout qualifer. - if (type.basetype == SPIRType::Image) + // 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) @@ -1586,9 +1598,11 @@ void CompilerGLSL::emit_resources() // If we're remapping separate samplers and images, only emit the combined samplers. if (skip_separate_image_sampler) { + // Sampler buffers are always used without a sampler, and they will also work in regular GL. + bool sampler_buffer = type.basetype == SPIRType::Image && type.image.dim == DimBuffer; bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1; bool separate_sampler = type.basetype == SPIRType::Sampler; - if (separate_image || separate_sampler) + if (!sampler_buffer && (separate_image || separate_sampler)) continue; } @@ -1614,6 +1628,11 @@ void CompilerGLSL::emit_resources() auto &var = id.get(); auto &type = get(var.basetype); + // HLSL output from glslang may emit interface variables which are "empty". + // Just avoid declaring them. + if (type_is_empty(type)) + continue; + if (var.storage != StorageClassFunction && type.pointer && (var.storage == StorageClassInput || var.storage == StorageClassOutput) && interface_variable_exists_in_entry_point(var.self) && !is_hidden_variable(var)) @@ -5087,12 +5106,14 @@ 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); break; case OpBitFieldSExtract: case OpBitFieldUExtract: - QFOP(bitfieldExtract); + // TODO: The signedness of inputs is strict in GLSL, but not in SPIR-V, bitcast if necessary. + TFOP(bitfieldExtract); break; case OpBitReverse: @@ -5900,7 +5921,13 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type) // If we're emulating subpassInput with samplers, force sampler2D // so we don't have to specify format. if (type.basetype == SPIRType::Image && type.image.dim != DimSubpassData) - res += type.image.sampled == 2 ? "image" : "texture"; + { + // Sampler buffers are always declared as samplerBuffer even though they might be separate images in the SPIR-V. + if (type.image.dim == DimBuffer && type.image.sampled == 1) + res += "sampler"; + else + res += type.image.sampled == 2 ? "image" : "texture"; + } else res += "sampler"; @@ -5974,7 +6001,6 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type) return image_type_glsl(type); case SPIRType::Sampler: - // Not really used. return "sampler"; case SPIRType::Void: diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index fdb2fb49..a32eb1df 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -444,6 +444,8 @@ protected: std::string emit_for_loop_initializers(const SPIRBlock &block); bool optimize_read_modify_write(const std::string &lhs, const std::string &rhs); void fixup_image_load_store_access(); + + bool type_is_empty(const SPIRType &type); }; } diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index ad8a9453..97e0b446 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -61,7 +61,6 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type) return image_type_glsl(type); case SPIRType::Sampler: - // Not really used. return "sampler"; case SPIRType::Void: @@ -1404,7 +1403,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "=="); else - BOP_CAST(== , SPIRType::Int); + BOP_CAST(==, SPIRType::Int); break; } @@ -1417,7 +1416,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "=="); else - BOP(== ); + BOP(==); break; } @@ -1429,7 +1428,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "!="); else - BOP_CAST(!= , SPIRType::Int); + BOP_CAST(!=, SPIRType::Int); break; } @@ -1442,7 +1441,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "!="); else - BOP(!= ); + BOP(!=); break; } @@ -1482,7 +1481,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">="); else - BOP_CAST(>= , type); + BOP_CAST(>=, type); break; } @@ -1494,7 +1493,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], ">="); else - BOP(>= ); + BOP(>=); break; } @@ -1534,7 +1533,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<="); else - BOP_CAST(<= , type); + BOP_CAST(<=, type); break; } @@ -1546,7 +1545,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (expression_type(ops[2]).vecsize > 1) emit_unrolled_binary_op(result_type, id, ops[2], ops[3], "<="); else - BOP(<= ); + BOP(<=); break; } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 77495405..e472c6ee 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -1851,7 +1851,6 @@ string CompilerMSL::type_to_glsl(const SPIRType &type) return image_type_glsl(type); case SPIRType::Sampler: - // Not really used. return "sampler"; case SPIRType::Void: