From: Ian Romanick Date: Tue, 18 Oct 2016 23:46:35 +0000 (-0700) Subject: glsl: Add "built-in" functions to do 64%64 => 64 modulus X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=695b04f7eb24bff108e8d85c476adb5cf9de6f2d;p=mesa.git glsl: Add "built-in" functions to do 64%64 => 64 modulus These functions are directly available in shaders. A #define is added to detect the presence. This allows these functions to be tested using piglit regardless of whether the driver uses them for lowering. The GLSL spec says that functions and macros beginning with __ are reserved for use by the implementation... hey, that's us! v2: Use function inlining. Signed-off-by: Ian Romanick Reviewed-by: Matt Turner --- diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 6d9ff4b504c..4a6c5afd65c 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -3103,6 +3103,10 @@ builtin_builder::create_builtins() generate_ir::idiv64(mem_ctx, integer_functions_supported), NULL); + add_function("__builtin_imod64", + generate_ir::imod64(mem_ctx, integer_functions_supported), + NULL); + add_function("__builtin_sign64", generate_ir::sign64(mem_ctx, integer_functions_supported), NULL); @@ -3111,6 +3115,10 @@ builtin_builder::create_builtins() generate_ir::udiv64(mem_ctx, integer_functions_supported), NULL); + add_function("__builtin_umod64", + generate_ir::umod64(mem_ctx, integer_functions_supported), + NULL); + add_function("__builtin_umul64", generate_ir::umul64(mem_ctx, integer_functions_supported), NULL); diff --git a/src/compiler/glsl/builtin_functions.h b/src/compiler/glsl/builtin_functions.h index ac1a8ccd1eb..7ae211b48aa 100644 --- a/src/compiler/glsl/builtin_functions.h +++ b/src/compiler/glsl/builtin_functions.h @@ -51,6 +51,12 @@ udiv64(void *mem_ctx, builtin_available_predicate avail); ir_function_signature * idiv64(void *mem_ctx, builtin_available_predicate avail); +ir_function_signature * +umod64(void *mem_ctx, builtin_available_predicate avail); + +ir_function_signature * +imod64(void *mem_ctx, builtin_available_predicate avail); + ir_function_signature * umul64(void *mem_ctx, builtin_available_predicate avail); diff --git a/src/compiler/glsl/builtin_int64.h b/src/compiler/glsl/builtin_int64.h index 5eaa4a8eac9..c3577afdee8 100644 --- a/src/compiler/glsl/builtin_int64.h +++ b/src/compiler/glsl/builtin_int64.h @@ -726,3 +726,477 @@ idiv64(void *mem_ctx, builtin_available_predicate avail) sig->replace_parameters(&sig_parameters); return sig; } +ir_function_signature * +umod64(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::uvec2_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r0096 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in); + sig_parameters.push_tail(r0096); + ir_variable *const r0097 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in); + sig_parameters.push_tail(r0097); + ir_variable *const r0098 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto); + body.emit(r0098); + body.emit(assign(r0098, r0096, 0x03)); + + ir_variable *const r0099 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r0099); + ir_variable *const r009A = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto); + body.emit(r009A); + ir_variable *const r009B = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto); + body.emit(r009B); + ir_variable *const r009C = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto); + body.emit(r009C); + body.emit(assign(r009C, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03)); + + ir_expression *const r009D = expr(ir_unop_find_msb, swizzle_y(r0097)); + body.emit(assign(r009B, add(r009D, body.constant(int(32))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r009F = equal(swizzle_y(r0097), body.constant(0u)); + ir_expression *const r00A0 = gequal(swizzle_y(r0096), swizzle_x(r0097)); + ir_expression *const r00A1 = logic_and(r009F, r00A0); + ir_if *f009E = new(mem_ctx) ir_if(operand(r00A1).val); + exec_list *const f009E_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f009E->then_instructions; + + ir_variable *const r00A2 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r00A2); + ir_variable *const r00A3 = body.make_temp(glsl_type::int_type, "findMSB_retval"); + body.emit(assign(r00A3, expr(ir_unop_find_msb, swizzle_x(r0097)), 0x01)); + + body.emit(assign(r009B, r00A3, 0x01)); + + body.emit(assign(r00A2, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f00A4 = new(mem_ctx) ir_loop(); + exec_list *const f00A4_parent_instructions = body.instructions; + + body.instructions = &f00A4->body_instructions; + + /* IF CONDITION */ + ir_expression *const r00A6 = less(r00A2, body.constant(int(1))); + ir_if *f00A5 = new(mem_ctx) ir_if(operand(r00A6).val); + exec_list *const f00A5_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00A5->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f00A5_parent_instructions; + body.emit(f00A5); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r00A8 = sub(body.constant(int(31)), r00A2); + ir_expression *const r00A9 = lequal(r00A3, r00A8); + ir_expression *const r00AA = lshift(swizzle_x(r0097), r00A2); + ir_expression *const r00AB = lequal(r00AA, swizzle_y(r0098)); + ir_expression *const r00AC = logic_and(r00A9, r00AB); + ir_if *f00A7 = new(mem_ctx) ir_if(operand(r00AC).val); + exec_list *const f00A7_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00A7->then_instructions; + + ir_expression *const r00AD = lshift(swizzle_x(r0097), r00A2); + body.emit(assign(r0098, sub(swizzle_y(r0098), r00AD), 0x02)); + + ir_expression *const r00AE = lshift(body.constant(1u), r00A2); + body.emit(assign(r009C, bit_or(swizzle_y(r009C), r00AE), 0x02)); + + + body.instructions = f00A7_parent_instructions; + body.emit(f00A7); + + /* END IF */ + + body.emit(assign(r00A2, add(r00A2, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f00A4_parent_instructions; + body.emit(f00A4); + + /* IF CONDITION */ + ir_expression *const r00B0 = lequal(swizzle_x(r0097), swizzle_y(r0098)); + ir_if *f00AF = new(mem_ctx) ir_if(operand(r00B0).val); + exec_list *const f00AF_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00AF->then_instructions; + + body.emit(assign(r0098, sub(swizzle_y(r0098), swizzle_x(r0097)), 0x02)); + + body.emit(assign(r009C, bit_or(swizzle_y(r009C), body.constant(1u)), 0x02)); + + + body.instructions = f00AF_parent_instructions; + body.emit(f00AF); + + /* END IF */ + + + body.instructions = f009E_parent_instructions; + body.emit(f009E); + + /* END IF */ + + ir_variable *const r00B1 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval"); + body.emit(assign(r00B1, expr(ir_unop_pack_uint_2x32, r0097), 0x01)); + + body.emit(assign(r009A, expr(ir_unop_pack_uint_2x32, r0098), 0x01)); + + body.emit(assign(r0099, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f00B2 = new(mem_ctx) ir_loop(); + exec_list *const f00B2_parent_instructions = body.instructions; + + body.instructions = &f00B2->body_instructions; + + /* IF CONDITION */ + ir_expression *const r00B4 = less(r0099, body.constant(int(1))); + ir_if *f00B3 = new(mem_ctx) ir_if(operand(r00B4).val); + exec_list *const f00B3_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00B3->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f00B3_parent_instructions; + body.emit(f00B3); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r00B6 = sub(body.constant(int(63)), r0099); + ir_expression *const r00B7 = lequal(r009B, r00B6); + ir_expression *const r00B8 = lshift(r00B1, r0099); + ir_expression *const r00B9 = lequal(r00B8, r009A); + ir_expression *const r00BA = logic_and(r00B7, r00B9); + ir_if *f00B5 = new(mem_ctx) ir_if(operand(r00BA).val); + exec_list *const f00B5_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00B5->then_instructions; + + ir_expression *const r00BB = lshift(r00B1, r0099); + body.emit(assign(r009A, sub(r009A, r00BB), 0x01)); + + ir_expression *const r00BC = lshift(body.constant(1u), r0099); + body.emit(assign(r009C, bit_or(swizzle_x(r009C), r00BC), 0x01)); + + + body.instructions = f00B5_parent_instructions; + body.emit(f00B5); + + /* END IF */ + + body.emit(assign(r0099, add(r0099, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f00B2_parent_instructions; + body.emit(f00B2); + + /* IF CONDITION */ + ir_expression *const r00BE = lequal(r00B1, r009A); + ir_if *f00BD = new(mem_ctx) ir_if(operand(r00BE).val); + exec_list *const f00BD_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00BD->then_instructions; + + body.emit(assign(r009A, sub(r009A, r00B1), 0x01)); + + body.emit(assign(r009C, bit_or(swizzle_x(r009C), body.constant(1u)), 0x01)); + + + body.instructions = f00BD_parent_instructions; + body.emit(f00BD); + + /* END IF */ + + ir_variable *const r00BF = body.make_temp(glsl_type::uvec4_type, "vec_ctor"); + body.emit(assign(r00BF, r009C, 0x03)); + + body.emit(assign(r00BF, expr(ir_unop_unpack_uint_2x32, r009A), 0x0c)); + + ir_swizzle *const r00C0 = swizzle(r00BF, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_X, SWIZZLE_X), 2); + body.emit(ret(r00C0)); + + sig->replace_parameters(&sig_parameters); + return sig; +} +ir_function_signature * +imod64(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::ivec2_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r00C1 = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_n", ir_var_function_in); + sig_parameters.push_tail(r00C1); + ir_variable *const r00C2 = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_d", ir_var_function_in); + sig_parameters.push_tail(r00C2); + ir_variable *const r00C3 = new(mem_ctx) ir_variable(glsl_type::bool_type, "negate", ir_var_auto); + body.emit(r00C3); + ir_expression *const r00C4 = less(swizzle_y(r00C1), body.constant(int(0))); + ir_expression *const r00C5 = less(swizzle_y(r00C2), body.constant(int(0))); + body.emit(assign(r00C3, nequal(r00C4, r00C5), 0x01)); + + ir_variable *const r00C6 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto); + body.emit(r00C6); + ir_expression *const r00C7 = expr(ir_unop_pack_int_2x32, r00C1); + ir_expression *const r00C8 = expr(ir_unop_abs, r00C7); + ir_expression *const r00C9 = expr(ir_unop_i642u64, r00C8); + body.emit(assign(r00C6, expr(ir_unop_unpack_uint_2x32, r00C9), 0x03)); + + ir_variable *const r00CA = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_auto); + body.emit(r00CA); + ir_expression *const r00CB = expr(ir_unop_pack_int_2x32, r00C2); + ir_expression *const r00CC = expr(ir_unop_abs, r00CB); + ir_expression *const r00CD = expr(ir_unop_i642u64, r00CC); + body.emit(assign(r00CA, expr(ir_unop_unpack_uint_2x32, r00CD), 0x03)); + + ir_variable *const r00CE = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r00CE); + ir_variable *const r00CF = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto); + body.emit(r00CF); + ir_variable *const r00D0 = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto); + body.emit(r00D0); + ir_variable *const r00D1 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto); + body.emit(r00D1); + body.emit(assign(r00D1, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03)); + + ir_expression *const r00D2 = expr(ir_unop_find_msb, swizzle_y(r00CA)); + body.emit(assign(r00D0, add(r00D2, body.constant(int(32))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r00D4 = equal(swizzle_y(r00CA), body.constant(0u)); + ir_expression *const r00D5 = gequal(swizzle_y(r00C6), swizzle_x(r00CA)); + ir_expression *const r00D6 = logic_and(r00D4, r00D5); + ir_if *f00D3 = new(mem_ctx) ir_if(operand(r00D6).val); + exec_list *const f00D3_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00D3->then_instructions; + + ir_variable *const r00D7 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r00D7); + ir_variable *const r00D8 = body.make_temp(glsl_type::int_type, "findMSB_retval"); + body.emit(assign(r00D8, expr(ir_unop_find_msb, swizzle_x(r00CA)), 0x01)); + + body.emit(assign(r00D0, r00D8, 0x01)); + + body.emit(assign(r00D7, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f00D9 = new(mem_ctx) ir_loop(); + exec_list *const f00D9_parent_instructions = body.instructions; + + body.instructions = &f00D9->body_instructions; + + /* IF CONDITION */ + ir_expression *const r00DB = less(r00D7, body.constant(int(1))); + ir_if *f00DA = new(mem_ctx) ir_if(operand(r00DB).val); + exec_list *const f00DA_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00DA->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f00DA_parent_instructions; + body.emit(f00DA); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r00DD = sub(body.constant(int(31)), r00D7); + ir_expression *const r00DE = lequal(r00D8, r00DD); + ir_expression *const r00DF = lshift(swizzle_x(r00CA), r00D7); + ir_expression *const r00E0 = lequal(r00DF, swizzle_y(r00C6)); + ir_expression *const r00E1 = logic_and(r00DE, r00E0); + ir_if *f00DC = new(mem_ctx) ir_if(operand(r00E1).val); + exec_list *const f00DC_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00DC->then_instructions; + + ir_expression *const r00E2 = lshift(swizzle_x(r00CA), r00D7); + body.emit(assign(r00C6, sub(swizzle_y(r00C6), r00E2), 0x02)); + + ir_expression *const r00E3 = lshift(body.constant(1u), r00D7); + body.emit(assign(r00D1, bit_or(swizzle_y(r00D1), r00E3), 0x02)); + + + body.instructions = f00DC_parent_instructions; + body.emit(f00DC); + + /* END IF */ + + body.emit(assign(r00D7, add(r00D7, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f00D9_parent_instructions; + body.emit(f00D9); + + /* IF CONDITION */ + ir_expression *const r00E5 = lequal(swizzle_x(r00CA), swizzle_y(r00C6)); + ir_if *f00E4 = new(mem_ctx) ir_if(operand(r00E5).val); + exec_list *const f00E4_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00E4->then_instructions; + + body.emit(assign(r00C6, sub(swizzle_y(r00C6), swizzle_x(r00CA)), 0x02)); + + body.emit(assign(r00D1, bit_or(swizzle_y(r00D1), body.constant(1u)), 0x02)); + + + body.instructions = f00E4_parent_instructions; + body.emit(f00E4); + + /* END IF */ + + + body.instructions = f00D3_parent_instructions; + body.emit(f00D3); + + /* END IF */ + + ir_variable *const r00E6 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval"); + body.emit(assign(r00E6, expr(ir_unop_pack_uint_2x32, r00CA), 0x01)); + + body.emit(assign(r00CF, expr(ir_unop_pack_uint_2x32, r00C6), 0x01)); + + body.emit(assign(r00CE, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f00E7 = new(mem_ctx) ir_loop(); + exec_list *const f00E7_parent_instructions = body.instructions; + + body.instructions = &f00E7->body_instructions; + + /* IF CONDITION */ + ir_expression *const r00E9 = less(r00CE, body.constant(int(1))); + ir_if *f00E8 = new(mem_ctx) ir_if(operand(r00E9).val); + exec_list *const f00E8_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00E8->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f00E8_parent_instructions; + body.emit(f00E8); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r00EB = sub(body.constant(int(63)), r00CE); + ir_expression *const r00EC = lequal(r00D0, r00EB); + ir_expression *const r00ED = lshift(r00E6, r00CE); + ir_expression *const r00EE = lequal(r00ED, r00CF); + ir_expression *const r00EF = logic_and(r00EC, r00EE); + ir_if *f00EA = new(mem_ctx) ir_if(operand(r00EF).val); + exec_list *const f00EA_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00EA->then_instructions; + + ir_expression *const r00F0 = lshift(r00E6, r00CE); + body.emit(assign(r00CF, sub(r00CF, r00F0), 0x01)); + + ir_expression *const r00F1 = lshift(body.constant(1u), r00CE); + body.emit(assign(r00D1, bit_or(swizzle_x(r00D1), r00F1), 0x01)); + + + body.instructions = f00EA_parent_instructions; + body.emit(f00EA); + + /* END IF */ + + body.emit(assign(r00CE, add(r00CE, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f00E7_parent_instructions; + body.emit(f00E7); + + /* IF CONDITION */ + ir_expression *const r00F3 = lequal(r00E6, r00CF); + ir_if *f00F2 = new(mem_ctx) ir_if(operand(r00F3).val); + exec_list *const f00F2_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00F2->then_instructions; + + body.emit(assign(r00CF, sub(r00CF, r00E6), 0x01)); + + body.emit(assign(r00D1, bit_or(swizzle_x(r00D1), body.constant(1u)), 0x01)); + + + body.instructions = f00F2_parent_instructions; + body.emit(f00F2); + + /* END IF */ + + ir_variable *const r00F4 = body.make_temp(glsl_type::uvec4_type, "vec_ctor"); + body.emit(assign(r00F4, r00D1, 0x03)); + + body.emit(assign(r00F4, expr(ir_unop_unpack_uint_2x32, r00CF), 0x0c)); + + ir_variable *const r00F5 = body.make_temp(glsl_type::ivec2_type, "conditional_tmp"); + /* IF CONDITION */ + ir_if *f00F6 = new(mem_ctx) ir_if(operand(r00C3).val); + exec_list *const f00F6_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f00F6->then_instructions; + + ir_swizzle *const r00F7 = swizzle(r00F4, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X), 2); + ir_expression *const r00F8 = expr(ir_unop_pack_uint_2x32, r00F7); + ir_expression *const r00F9 = expr(ir_unop_u642i64, r00F8); + ir_expression *const r00FA = neg(r00F9); + body.emit(assign(r00F5, expr(ir_unop_unpack_int_2x32, r00FA), 0x03)); + + + /* ELSE INSTRUCTIONS */ + body.instructions = &f00F6->else_instructions; + + ir_swizzle *const r00FB = swizzle(r00F4, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X), 2); + body.emit(assign(r00F5, expr(ir_unop_u2i, r00FB), 0x03)); + + + body.instructions = f00F6_parent_instructions; + body.emit(f00F6); + + /* END IF */ + + body.emit(ret(r00F5)); + + sig->replace_parameters(&sig_parameters); + return sig; +} diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index d801cf8a9d7..e113253061f 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -2346,7 +2346,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio add_builtin_define(parser, "__have_builtin_builtin_sign64", 1); add_builtin_define(parser, "__have_builtin_builtin_umul64", 1); add_builtin_define(parser, "__have_builtin_builtin_udiv64", 1); + add_builtin_define(parser, "__have_builtin_builtin_umod64", 1); add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1); + add_builtin_define(parser, "__have_builtin_builtin_imod64", 1); } } diff --git a/src/compiler/glsl/int64.glsl b/src/compiler/glsl/int64.glsl index 84e80ee349b..b1036e379c9 100644 --- a/src/compiler/glsl/int64.glsl +++ b/src/compiler/glsl/int64.glsl @@ -101,3 +101,21 @@ idiv64(ivec2 _n, ivec2 _d) return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot); } + +uvec2 +umod64(uvec2 n, uvec2 d) +{ + return udivmod64(n, d).zw; +} + +ivec2 +imod64(ivec2 _n, ivec2 _d) +{ + const bool negate = (_n.y < 0) != (_d.y < 0); + uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n)))); + uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d)))); + + uvec2 rem = udivmod64(n, d).zy; + + return negate ? unpackInt2x32(-int64_t(packUint2x32(rem))) : ivec2(rem); +}