From: Ian Romanick Date: Tue, 18 Oct 2016 00:54:40 +0000 (-0700) Subject: glsl: Add "built-in" functions to do 64/64 => 64 division X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=012f2995c307a83212a88ff18e13bf7be006cd77;p=mesa.git glsl: Add "built-in" functions to do 64/64 => 64 division 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 f64ab6a5f33..6d9ff4b504c 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -3099,10 +3099,18 @@ builtin_builder::create_builtins() add_function("allInvocationsARB", _vote(ir_unop_vote_all), NULL); add_function("allInvocationsEqualARB", _vote(ir_unop_vote_eq), NULL); + add_function("__builtin_idiv64", + generate_ir::idiv64(mem_ctx, integer_functions_supported), + NULL); + add_function("__builtin_sign64", generate_ir::sign64(mem_ctx, integer_functions_supported), NULL); + add_function("__builtin_udiv64", + generate_ir::udiv64(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 c66f523f692..ac1a8ccd1eb 100644 --- a/src/compiler/glsl/builtin_functions.h +++ b/src/compiler/glsl/builtin_functions.h @@ -45,6 +45,12 @@ _mesa_glsl_release_builtin_functions(void); namespace generate_ir { +ir_function_signature * +udiv64(void *mem_ctx, builtin_available_predicate avail); + +ir_function_signature * +idiv64(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 c12565d14c7..5eaa4a8eac9 100644 --- a/src/compiler/glsl/builtin_int64.h +++ b/src/compiler/glsl/builtin_int64.h @@ -54,3 +54,675 @@ sign64(void *mem_ctx, builtin_available_predicate avail) sig->replace_parameters(&sig_parameters); return sig; } +ir_function_signature * +udivmod64(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::uvec4_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r000C = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in); + sig_parameters.push_tail(r000C); + ir_variable *const r000D = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in); + sig_parameters.push_tail(r000D); + ir_variable *const r000E = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r000E); + ir_variable *const r000F = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto); + body.emit(r000F); + ir_variable *const r0010 = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto); + body.emit(r0010); + ir_variable *const r0011 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto); + body.emit(r0011); + body.emit(assign(r0011, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03)); + + ir_expression *const r0012 = expr(ir_unop_find_msb, swizzle_y(r000D)); + body.emit(assign(r0010, add(r0012, body.constant(int(32))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r0014 = equal(swizzle_y(r000D), body.constant(0u)); + ir_expression *const r0015 = gequal(swizzle_y(r000C), swizzle_x(r000D)); + ir_expression *const r0016 = logic_and(r0014, r0015); + ir_if *f0013 = new(mem_ctx) ir_if(operand(r0016).val); + exec_list *const f0013_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0013->then_instructions; + + ir_variable *const r0017 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r0017); + ir_variable *const r0018 = body.make_temp(glsl_type::int_type, "findMSB_retval"); + body.emit(assign(r0018, expr(ir_unop_find_msb, swizzle_x(r000D)), 0x01)); + + body.emit(assign(r0010, r0018, 0x01)); + + body.emit(assign(r0017, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0019 = new(mem_ctx) ir_loop(); + exec_list *const f0019_parent_instructions = body.instructions; + + body.instructions = &f0019->body_instructions; + + /* IF CONDITION */ + ir_expression *const r001B = less(r0017, body.constant(int(1))); + ir_if *f001A = new(mem_ctx) ir_if(operand(r001B).val); + exec_list *const f001A_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f001A->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f001A_parent_instructions; + body.emit(f001A); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r001D = sub(body.constant(int(31)), r0017); + ir_expression *const r001E = lequal(r0018, r001D); + ir_expression *const r001F = lshift(swizzle_x(r000D), r0017); + ir_expression *const r0020 = lequal(r001F, swizzle_y(r000C)); + ir_expression *const r0021 = logic_and(r001E, r0020); + ir_if *f001C = new(mem_ctx) ir_if(operand(r0021).val); + exec_list *const f001C_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f001C->then_instructions; + + ir_expression *const r0022 = lshift(swizzle_x(r000D), r0017); + body.emit(assign(r000C, sub(swizzle_y(r000C), r0022), 0x02)); + + ir_expression *const r0023 = lshift(body.constant(1u), r0017); + body.emit(assign(r0011, bit_or(swizzle_y(r0011), r0023), 0x02)); + + + body.instructions = f001C_parent_instructions; + body.emit(f001C); + + /* END IF */ + + body.emit(assign(r0017, add(r0017, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0019_parent_instructions; + body.emit(f0019); + + /* IF CONDITION */ + ir_expression *const r0025 = lequal(swizzle_x(r000D), swizzle_y(r000C)); + ir_if *f0024 = new(mem_ctx) ir_if(operand(r0025).val); + exec_list *const f0024_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0024->then_instructions; + + body.emit(assign(r000C, sub(swizzle_y(r000C), swizzle_x(r000D)), 0x02)); + + body.emit(assign(r0011, bit_or(swizzle_y(r0011), body.constant(1u)), 0x02)); + + + body.instructions = f0024_parent_instructions; + body.emit(f0024); + + /* END IF */ + + + body.instructions = f0013_parent_instructions; + body.emit(f0013); + + /* END IF */ + + ir_variable *const r0026 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval"); + body.emit(assign(r0026, expr(ir_unop_pack_uint_2x32, r000D), 0x01)); + + body.emit(assign(r000F, expr(ir_unop_pack_uint_2x32, r000C), 0x01)); + + body.emit(assign(r000E, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0027 = new(mem_ctx) ir_loop(); + exec_list *const f0027_parent_instructions = body.instructions; + + body.instructions = &f0027->body_instructions; + + /* IF CONDITION */ + ir_expression *const r0029 = less(r000E, body.constant(int(1))); + ir_if *f0028 = new(mem_ctx) ir_if(operand(r0029).val); + exec_list *const f0028_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0028->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f0028_parent_instructions; + body.emit(f0028); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r002B = sub(body.constant(int(63)), r000E); + ir_expression *const r002C = lequal(r0010, r002B); + ir_expression *const r002D = lshift(r0026, r000E); + ir_expression *const r002E = lequal(r002D, r000F); + ir_expression *const r002F = logic_and(r002C, r002E); + ir_if *f002A = new(mem_ctx) ir_if(operand(r002F).val); + exec_list *const f002A_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f002A->then_instructions; + + ir_expression *const r0030 = lshift(r0026, r000E); + body.emit(assign(r000F, sub(r000F, r0030), 0x01)); + + ir_expression *const r0031 = lshift(body.constant(1u), r000E); + body.emit(assign(r0011, bit_or(swizzle_x(r0011), r0031), 0x01)); + + + body.instructions = f002A_parent_instructions; + body.emit(f002A); + + /* END IF */ + + body.emit(assign(r000E, add(r000E, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0027_parent_instructions; + body.emit(f0027); + + /* IF CONDITION */ + ir_expression *const r0033 = lequal(r0026, r000F); + ir_if *f0032 = new(mem_ctx) ir_if(operand(r0033).val); + exec_list *const f0032_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0032->then_instructions; + + body.emit(assign(r000F, sub(r000F, r0026), 0x01)); + + body.emit(assign(r0011, bit_or(swizzle_x(r0011), body.constant(1u)), 0x01)); + + + body.instructions = f0032_parent_instructions; + body.emit(f0032); + + /* END IF */ + + ir_variable *const r0034 = body.make_temp(glsl_type::uvec4_type, "vec_ctor"); + body.emit(assign(r0034, r0011, 0x03)); + + body.emit(assign(r0034, expr(ir_unop_unpack_uint_2x32, r000F), 0x0c)); + + body.emit(ret(r0034)); + + sig->replace_parameters(&sig_parameters); + return sig; +} +ir_function_signature * +udiv64(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 r0035 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in); + sig_parameters.push_tail(r0035); + ir_variable *const r0036 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in); + sig_parameters.push_tail(r0036); + ir_variable *const r0037 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto); + body.emit(r0037); + body.emit(assign(r0037, r0035, 0x03)); + + ir_variable *const r0038 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r0038); + ir_variable *const r0039 = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto); + body.emit(r0039); + ir_variable *const r003A = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto); + body.emit(r003A); + ir_variable *const r003B = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto); + body.emit(r003B); + body.emit(assign(r003B, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03)); + + ir_expression *const r003C = expr(ir_unop_find_msb, swizzle_y(r0036)); + body.emit(assign(r003A, add(r003C, body.constant(int(32))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r003E = equal(swizzle_y(r0036), body.constant(0u)); + ir_expression *const r003F = gequal(swizzle_y(r0035), swizzle_x(r0036)); + ir_expression *const r0040 = logic_and(r003E, r003F); + ir_if *f003D = new(mem_ctx) ir_if(operand(r0040).val); + exec_list *const f003D_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f003D->then_instructions; + + ir_variable *const r0041 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r0041); + ir_variable *const r0042 = body.make_temp(glsl_type::int_type, "findMSB_retval"); + body.emit(assign(r0042, expr(ir_unop_find_msb, swizzle_x(r0036)), 0x01)); + + body.emit(assign(r003A, r0042, 0x01)); + + body.emit(assign(r0041, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0043 = new(mem_ctx) ir_loop(); + exec_list *const f0043_parent_instructions = body.instructions; + + body.instructions = &f0043->body_instructions; + + /* IF CONDITION */ + ir_expression *const r0045 = less(r0041, body.constant(int(1))); + ir_if *f0044 = new(mem_ctx) ir_if(operand(r0045).val); + exec_list *const f0044_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0044->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f0044_parent_instructions; + body.emit(f0044); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r0047 = sub(body.constant(int(31)), r0041); + ir_expression *const r0048 = lequal(r0042, r0047); + ir_expression *const r0049 = lshift(swizzle_x(r0036), r0041); + ir_expression *const r004A = lequal(r0049, swizzle_y(r0037)); + ir_expression *const r004B = logic_and(r0048, r004A); + ir_if *f0046 = new(mem_ctx) ir_if(operand(r004B).val); + exec_list *const f0046_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0046->then_instructions; + + ir_expression *const r004C = lshift(swizzle_x(r0036), r0041); + body.emit(assign(r0037, sub(swizzle_y(r0037), r004C), 0x02)); + + ir_expression *const r004D = lshift(body.constant(1u), r0041); + body.emit(assign(r003B, bit_or(swizzle_y(r003B), r004D), 0x02)); + + + body.instructions = f0046_parent_instructions; + body.emit(f0046); + + /* END IF */ + + body.emit(assign(r0041, add(r0041, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0043_parent_instructions; + body.emit(f0043); + + /* IF CONDITION */ + ir_expression *const r004F = lequal(swizzle_x(r0036), swizzle_y(r0037)); + ir_if *f004E = new(mem_ctx) ir_if(operand(r004F).val); + exec_list *const f004E_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f004E->then_instructions; + + body.emit(assign(r0037, sub(swizzle_y(r0037), swizzle_x(r0036)), 0x02)); + + body.emit(assign(r003B, bit_or(swizzle_y(r003B), body.constant(1u)), 0x02)); + + + body.instructions = f004E_parent_instructions; + body.emit(f004E); + + /* END IF */ + + + body.instructions = f003D_parent_instructions; + body.emit(f003D); + + /* END IF */ + + ir_variable *const r0050 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval"); + body.emit(assign(r0050, expr(ir_unop_pack_uint_2x32, r0036), 0x01)); + + body.emit(assign(r0039, expr(ir_unop_pack_uint_2x32, r0037), 0x01)); + + body.emit(assign(r0038, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0051 = new(mem_ctx) ir_loop(); + exec_list *const f0051_parent_instructions = body.instructions; + + body.instructions = &f0051->body_instructions; + + /* IF CONDITION */ + ir_expression *const r0053 = less(r0038, body.constant(int(1))); + ir_if *f0052 = new(mem_ctx) ir_if(operand(r0053).val); + exec_list *const f0052_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0052->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f0052_parent_instructions; + body.emit(f0052); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r0055 = sub(body.constant(int(63)), r0038); + ir_expression *const r0056 = lequal(r003A, r0055); + ir_expression *const r0057 = lshift(r0050, r0038); + ir_expression *const r0058 = lequal(r0057, r0039); + ir_expression *const r0059 = logic_and(r0056, r0058); + ir_if *f0054 = new(mem_ctx) ir_if(operand(r0059).val); + exec_list *const f0054_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0054->then_instructions; + + ir_expression *const r005A = lshift(r0050, r0038); + body.emit(assign(r0039, sub(r0039, r005A), 0x01)); + + ir_expression *const r005B = lshift(body.constant(1u), r0038); + body.emit(assign(r003B, bit_or(swizzle_x(r003B), r005B), 0x01)); + + + body.instructions = f0054_parent_instructions; + body.emit(f0054); + + /* END IF */ + + body.emit(assign(r0038, add(r0038, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0051_parent_instructions; + body.emit(f0051); + + /* IF CONDITION */ + ir_expression *const r005D = lequal(r0050, r0039); + ir_if *f005C = new(mem_ctx) ir_if(operand(r005D).val); + exec_list *const f005C_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f005C->then_instructions; + + body.emit(assign(r0039, sub(r0039, r0050), 0x01)); + + body.emit(assign(r003B, bit_or(swizzle_x(r003B), body.constant(1u)), 0x01)); + + + body.instructions = f005C_parent_instructions; + body.emit(f005C); + + /* END IF */ + + body.emit(ret(r003B)); + + sig->replace_parameters(&sig_parameters); + return sig; +} +ir_function_signature * +idiv64(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 r005E = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_n", ir_var_function_in); + sig_parameters.push_tail(r005E); + ir_variable *const r005F = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_d", ir_var_function_in); + sig_parameters.push_tail(r005F); + ir_variable *const r0060 = new(mem_ctx) ir_variable(glsl_type::bool_type, "negate", ir_var_auto); + body.emit(r0060); + ir_expression *const r0061 = less(swizzle_y(r005E), body.constant(int(0))); + ir_expression *const r0062 = less(swizzle_y(r005F), body.constant(int(0))); + body.emit(assign(r0060, nequal(r0061, r0062), 0x01)); + + ir_variable *const r0063 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto); + body.emit(r0063); + ir_expression *const r0064 = expr(ir_unop_pack_int_2x32, r005E); + ir_expression *const r0065 = expr(ir_unop_abs, r0064); + ir_expression *const r0066 = expr(ir_unop_i642u64, r0065); + body.emit(assign(r0063, expr(ir_unop_unpack_uint_2x32, r0066), 0x03)); + + ir_variable *const r0067 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_auto); + body.emit(r0067); + ir_expression *const r0068 = expr(ir_unop_pack_int_2x32, r005F); + ir_expression *const r0069 = expr(ir_unop_abs, r0068); + ir_expression *const r006A = expr(ir_unop_i642u64, r0069); + body.emit(assign(r0067, expr(ir_unop_unpack_uint_2x32, r006A), 0x03)); + + ir_variable *const r006B = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r006B); + ir_variable *const r006C = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto); + body.emit(r006C); + ir_variable *const r006D = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto); + body.emit(r006D); + ir_variable *const r006E = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto); + body.emit(r006E); + body.emit(assign(r006E, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03)); + + ir_expression *const r006F = expr(ir_unop_find_msb, swizzle_y(r0067)); + body.emit(assign(r006D, add(r006F, body.constant(int(32))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r0071 = equal(swizzle_y(r0067), body.constant(0u)); + ir_expression *const r0072 = gequal(swizzle_y(r0063), swizzle_x(r0067)); + ir_expression *const r0073 = logic_and(r0071, r0072); + ir_if *f0070 = new(mem_ctx) ir_if(operand(r0073).val); + exec_list *const f0070_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0070->then_instructions; + + ir_variable *const r0074 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto); + body.emit(r0074); + ir_variable *const r0075 = body.make_temp(glsl_type::int_type, "findMSB_retval"); + body.emit(assign(r0075, expr(ir_unop_find_msb, swizzle_x(r0067)), 0x01)); + + body.emit(assign(r006D, r0075, 0x01)); + + body.emit(assign(r0074, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0076 = new(mem_ctx) ir_loop(); + exec_list *const f0076_parent_instructions = body.instructions; + + body.instructions = &f0076->body_instructions; + + /* IF CONDITION */ + ir_expression *const r0078 = less(r0074, body.constant(int(1))); + ir_if *f0077 = new(mem_ctx) ir_if(operand(r0078).val); + exec_list *const f0077_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0077->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f0077_parent_instructions; + body.emit(f0077); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r007A = sub(body.constant(int(31)), r0074); + ir_expression *const r007B = lequal(r0075, r007A); + ir_expression *const r007C = lshift(swizzle_x(r0067), r0074); + ir_expression *const r007D = lequal(r007C, swizzle_y(r0063)); + ir_expression *const r007E = logic_and(r007B, r007D); + ir_if *f0079 = new(mem_ctx) ir_if(operand(r007E).val); + exec_list *const f0079_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0079->then_instructions; + + ir_expression *const r007F = lshift(swizzle_x(r0067), r0074); + body.emit(assign(r0063, sub(swizzle_y(r0063), r007F), 0x02)); + + ir_expression *const r0080 = lshift(body.constant(1u), r0074); + body.emit(assign(r006E, bit_or(swizzle_y(r006E), r0080), 0x02)); + + + body.instructions = f0079_parent_instructions; + body.emit(f0079); + + /* END IF */ + + body.emit(assign(r0074, add(r0074, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0076_parent_instructions; + body.emit(f0076); + + /* IF CONDITION */ + ir_expression *const r0082 = lequal(swizzle_x(r0067), swizzle_y(r0063)); + ir_if *f0081 = new(mem_ctx) ir_if(operand(r0082).val); + exec_list *const f0081_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0081->then_instructions; + + body.emit(assign(r0063, sub(swizzle_y(r0063), swizzle_x(r0067)), 0x02)); + + body.emit(assign(r006E, bit_or(swizzle_y(r006E), body.constant(1u)), 0x02)); + + + body.instructions = f0081_parent_instructions; + body.emit(f0081); + + /* END IF */ + + + body.instructions = f0070_parent_instructions; + body.emit(f0070); + + /* END IF */ + + ir_variable *const r0083 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval"); + body.emit(assign(r0083, expr(ir_unop_pack_uint_2x32, r0067), 0x01)); + + body.emit(assign(r006C, expr(ir_unop_pack_uint_2x32, r0063), 0x01)); + + body.emit(assign(r006B, body.constant(int(31)), 0x01)); + + /* LOOP BEGIN */ + ir_loop *f0084 = new(mem_ctx) ir_loop(); + exec_list *const f0084_parent_instructions = body.instructions; + + body.instructions = &f0084->body_instructions; + + /* IF CONDITION */ + ir_expression *const r0086 = less(r006B, body.constant(int(1))); + ir_if *f0085 = new(mem_ctx) ir_if(operand(r0086).val); + exec_list *const f0085_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0085->then_instructions; + + body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break)); + + + body.instructions = f0085_parent_instructions; + body.emit(f0085); + + /* END IF */ + + /* IF CONDITION */ + ir_expression *const r0088 = sub(body.constant(int(63)), r006B); + ir_expression *const r0089 = lequal(r006D, r0088); + ir_expression *const r008A = lshift(r0083, r006B); + ir_expression *const r008B = lequal(r008A, r006C); + ir_expression *const r008C = logic_and(r0089, r008B); + ir_if *f0087 = new(mem_ctx) ir_if(operand(r008C).val); + exec_list *const f0087_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0087->then_instructions; + + ir_expression *const r008D = lshift(r0083, r006B); + body.emit(assign(r006C, sub(r006C, r008D), 0x01)); + + ir_expression *const r008E = lshift(body.constant(1u), r006B); + body.emit(assign(r006E, bit_or(swizzle_x(r006E), r008E), 0x01)); + + + body.instructions = f0087_parent_instructions; + body.emit(f0087); + + /* END IF */ + + body.emit(assign(r006B, add(r006B, body.constant(int(-1))), 0x01)); + + /* LOOP END */ + + body.instructions = f0084_parent_instructions; + body.emit(f0084); + + /* IF CONDITION */ + ir_expression *const r0090 = lequal(r0083, r006C); + ir_if *f008F = new(mem_ctx) ir_if(operand(r0090).val); + exec_list *const f008F_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f008F->then_instructions; + + body.emit(assign(r006C, sub(r006C, r0083), 0x01)); + + body.emit(assign(r006E, bit_or(swizzle_x(r006E), body.constant(1u)), 0x01)); + + + body.instructions = f008F_parent_instructions; + body.emit(f008F); + + /* END IF */ + + ir_variable *const r0091 = body.make_temp(glsl_type::ivec2_type, "conditional_tmp"); + /* IF CONDITION */ + ir_if *f0092 = new(mem_ctx) ir_if(operand(r0060).val); + exec_list *const f0092_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0092->then_instructions; + + ir_expression *const r0093 = expr(ir_unop_pack_uint_2x32, r006E); + ir_expression *const r0094 = expr(ir_unop_u642i64, r0093); + ir_expression *const r0095 = neg(r0094); + body.emit(assign(r0091, expr(ir_unop_unpack_int_2x32, r0095), 0x03)); + + + /* ELSE INSTRUCTIONS */ + body.instructions = &f0092->else_instructions; + + body.emit(assign(r0091, expr(ir_unop_u2i, r006E), 0x03)); + + + body.instructions = f0092_parent_instructions; + body.emit(f0092); + + /* END IF */ + + body.emit(ret(r0091)); + + 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 39a7a89258f..d801cf8a9d7 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -2345,6 +2345,8 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (parser->extension_list->MESA_shader_integer_functions) { 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_idiv64", 1); } } diff --git a/src/compiler/glsl/int64.glsl b/src/compiler/glsl/int64.glsl index a2bec011e3e..84e80ee349b 100644 --- a/src/compiler/glsl/int64.glsl +++ b/src/compiler/glsl/int64.glsl @@ -4,8 +4,9 @@ * * Using version 1.40+ prevents built-in variables from being included. */ -#version 140 -#extension GL_MESA_shader_integer_functions: require +#version 400 +#extension GL_ARB_gpu_shader_int64: require +#extension GL_ARB_shading_language_420pack: require uvec2 umul64(uvec2 a, uvec2 b) @@ -28,3 +29,75 @@ sign64(ivec2 a) return result; } + +uvec4 +udivmod64(uvec2 n, uvec2 d) +{ + uvec2 quot = uvec2(0U, 0U); + int log2_denom = findMSB(d.y) + 32; + + /* If the upper 32 bits of denom are non-zero, it is impossible for shifts + * greater than 32 bits to occur. If the upper 32 bits of the numerator + * are zero, it is impossible for (denom << [63, 32]) <= numer unless + * denom == 0. + */ + if (d.y == 0 && n.y >= d.x) { + log2_denom = findMSB(d.x); + + /* Since the upper 32 bits of denom are zero, log2_denom <= 31 and we + * don't have to compare log2_denom inside the loop as is done in the + * general case (below). + */ + for (int i = 31; i >= 1; i--) { + if (log2_denom <= 31 - i && (d.x << i) <= n.y) { + n.y -= d.x << i; + quot.y |= 1U << i; + } + } + + /* log2_denom is always <= 31, so manually peel the last loop + * iteration. + */ + if (d.x <= n.y) { + n.y -= d.x; + quot.y |= 1U; + } + } + + uint64_t d64 = packUint2x32(d); + uint64_t n64 = packUint2x32(n); + for (int i = 31; i >= 1; i--) { + if (log2_denom <= 63 - i && (d64 << i) <= n64) { + n64 -= d64 << i; + quot.x |= 1U << i; + } + } + + /* log2_denom is always <= 63, so manually peel the last loop + * iteration. + */ + if (d64 <= n64) { + n64 -= d64; + quot.x |= 1U; + } + + return uvec4(quot, unpackUint2x32(n64)); +} + +uvec2 +udiv64(uvec2 n, uvec2 d) +{ + return udivmod64(n, d).xy; +} + +ivec2 +idiv64(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 quot = udivmod64(n, d).xy; + + return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot); +}