// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#version 460

//
// Prefix sum the coarse histograms.
//

// clang-format off
#extension GL_GOOGLE_include_directive             : require
#extension GL_EXT_control_flow_attributes          : require
#extension GL_KHR_shader_subgroup_arithmetic       : require
#extension GL_KHR_shader_subgroup_ballot           : require
// clang-format on

//
//
//
#include "config.h"

//
// Buffer reference macros and push constants
//
#include "bufref.h"
#include "push.h"

//
//
//
RS_STRUCT_PUSH_PREFIX();

layout(push_constant) uniform block_push
{
  rs_push_prefix push;
};

//
// Subgroup uniform support
//
#if defined(RS_HISTOGRAM_SUBGROUP_UNIFORM_DISABLE) && defined(GL_EXT_subgroupuniform_qualifier)
#extension GL_EXT_subgroupuniform_qualifier : required
#define RS_SUBGROUP_UNIFORM subgroupuniformEXT
#else
#define RS_SUBGROUP_UNIFORM
#endif

//
// Local macros
//
// clang-format off
#define RS_KEYVAL_SIZE          (RS_KEYVAL_DWORDS * 4)
#define RS_WORKGROUP_SIZE       (RS_PREFIX_WORKGROUP_SIZE)
#define RS_SUBGROUP_SIZE        (1 << RS_PREFIX_SUBGROUP_SIZE_LOG2)
#define RS_WORKGROUP_SUBGROUPS  (RS_WORKGROUP_SIZE / RS_SUBGROUP_SIZE)
// clang-format on

//
//
//
layout(local_size_x_id = RS_PREFIX_WORKGROUP_SIZE_ID) in;

//
// Histogram buffer reference
//
layout(buffer_reference, std430) buffer buffer_rs_histograms
{
  uint32_t extent[];
};

//
// Load prefix limits before loading function
//
#include "prefix_limits.h"

//----------------------------------------
shared uint32_t smem_sweep0[RS_SWEEP_0_SIZE];

#define RS_PREFIX_SWEEP0(idx_) smem_sweep0[idx_]
//----------------------------------------

//----------------------------------------
shared uint32_t smem_sweep1[RS_SWEEP_1_SIZE];

#define RS_PREFIX_SWEEP1(idx_) smem_sweep1[idx_]
//----------------------------------------

//----------------------------------------
shared uint32_t smem_sweep2[RS_SWEEP_2_SIZE];

#define RS_PREFIX_SWEEP2(idx_) smem_sweep2[idx_]
//----------------------------------------

//
// Define function arguments
//
#define RS_PREFIX_ARGS buffer_rs_histograms rs_histograms

//
// Define load/store functions
//
// clang-format off
#define RS_PREFIX_LOAD(idx_)   rs_histograms.extent[idx_]
#define RS_PREFIX_STORE(idx_)  rs_histograms.extent[idx_]
// clang-format on

//
// Load prefix function
//
#include "prefix.h"

//
// Exclusive prefix of uint32_t[256]
//
void
main()
{
  //
  // Define buffer reference to read histograms
  //
  // NOTE(allanmac): The histogram buffer reference could be adjusted
  // on the host to save a couple instructions at the cost of added
  // complexity.
  //
  const uint32_t invocation_id = RS_WORKGROUP_SUBGROUPS == 1 ? gl_SubgroupInvocationID : gl_LocalInvocationID.x;

  RS_SUBGROUP_UNIFORM
  const uint32_t histograms_base   = ((RS_KEYVAL_SIZE - 1 - gl_WorkGroupID.x) * RS_RADIX_SIZE);
  const uint32_t histograms_offset = (histograms_base + invocation_id) * 4;

  RS_BUFREF_DEFINE_AT_OFFSET_UINT32(buffer_rs_histograms,
                                    rs_histograms,
                                    push.devaddr_histograms,
                                    histograms_offset);


  //
  // Compute exclusive prefix of uint32_t[256]
  //
  rs_prefix(rs_histograms);
}

//
//
//
