/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2022 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xesl.xesli"

#if XE_GUEST_OUTPUT_DITHER
  #include "dither_8bpc.xesli"
#endif  // XE_GUEST_OUTPUT_DITHER

push_const_begin_xe(b0, space0)
  // 16 used by the vertex shader (GLSL push constant offsets are across
  // stages).
  block_offset_member_xe(16, c0.x, int2_xe, xe_bilinear_output_offset)
  block_offset_member_xe(24, c0.z, float2_xe, xe_bilinear_output_size_inv)
push_const_end_xe

entry_outputs_begin_xe
  entry_out_target_xe(float4_xe, xe_bilinear_color, 0)
entry_outputs_end_stage_inputs_begin_xe
entry_stage_inputs_end_bindings_begin_pixel_xe
  push_const_binding_xe(buffer(0))
  entry_binding_next_xe
  texture_xe(texture_2d_xe, xe_bilinear_source, set=0, binding=0, t0, space0,
             texture(0))
  entry_binding_next_xe
  sampler_state_xe(xe_bilinear_sampler, set=0, binding=1, s0, space0,
                   sampler(0))
entry_bindings_end_inputs_begin_xe
  entry_in_pixel_coord_xe
entry_inputs_end_code_begin_xe
{
  uint2_xe pixel_coord = uint2_xe(int2_xe(in_pixel_coord_xe.xy) -
                                  push_const_xe(xe_bilinear_output_offset));
  float4_xe bilinear_color;
  // + 0.5 so the origin is at the pixel center, and at 1:1 the original pixel
  // is taken.
  // Interpolating the four colors in the perceptual space because doing it in
  // linear space causes, in particular, bright text on a dark background to
  // become too thick, and aliasing of bright parts on top of dark areas to be
  // too apparent (4D5307E6 HUD, for example, mainly the edges of the
  // multiplayer score bars).
  bilinear_color.rgb =
      sample_sep_lod_2d_xe(
          xe_bilinear_source, xe_bilinear_sampler,
          (float2_xe(pixel_coord) + 0.5f) *
              push_const_xe(xe_bilinear_output_size_inv),
          0.0f).rgb;
  #if XE_GUEST_OUTPUT_DITHER
    // Clamping because on Vulkan, the surface may specify any format, including
    // floating-point.
    bilinear_color.rgb =
        saturate_xe(bilinear_color.rgb + XeDitherOffset8bpc(pixel_coord));
  #endif  // XE_GUEST_OUTPUT_DITHER
  bilinear_color.a = 1.0f;
  out_xe(xe_bilinear_color) = bilinear_color;
}
entry_code_end_xe
