dst_x = resource[offset] + 1
- resource[offset] = dst_x < src_x ? dst_x : 0
+ resource[offset] = dst_x <= src_x ? dst_x : 0
.. opcode:: ATOMDEC_WRAP - Atomic decrement + wrap around
args.data[num_data++] =
ac_to_integer(&ctx->ac, lp_build_emit_fetch(bld_base, inst, 2, 0));
- if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMINC_WRAP) {
- /* ATOMIC_INC instruction does:
- * value = (value + 1) % (data + 1)
- * but we want:
- * value = (value + 1) % data
- * So replace 'data' by 'data - 1'.
- */
- args.data[0] = LLVMBuildSub(ctx->ac.builder,
- args.data[0],
- ctx->ac.i32_1, "");
- }
-
args.cache_policy = get_cache_policy(ctx, inst, true, false, false);
if (inst->Src[0].Register.File == TGSI_FILE_BUFFER) {
case ir_intrinsic_image_atomic_comp_swap:
opcode = TGSI_OPCODE_ATOMCAS;
break;
- case ir_intrinsic_image_atomic_inc_wrap:
+ case ir_intrinsic_image_atomic_inc_wrap: {
+ /* There's a bit of disagreement between GLSL and the hardware. The
+ * hardware wants to wrap after the given wrap value, while GLSL
+ * wants to wrap at the value. Subtract 1 to make up the difference.
+ */
+ st_src_reg wrap = get_temp(glsl_type::uint_type);
+ emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(wrap),
+ arg1, st_src_reg_for_int(-1));
+ arg1 = wrap;
opcode = TGSI_OPCODE_ATOMINC_WRAP;
break;
+ }
case ir_intrinsic_image_atomic_dec_wrap:
opcode = TGSI_OPCODE_ATOMDEC_WRAP;
break;