/* SPDX-FileCopyrightText: 2022 Blender Authors
 *
 * SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup draw
 */

#ifndef GPU_SHADER
#  include "BLI_span.hh"
#  include "GPU_shader_shared_utils.hh"

namespace blender::draw::command {

#endif

/* -------------------------------------------------------------------- */
/** \name Multi Draw
 * \{ */

/**
 * A DrawGroup allow to split the command stream into batch-able chunks of commands with
 * the same render state.
 */
struct DrawGroup {
  /** Index of next #DrawGroup from the same header. */
  uint next;

  /**
   * IMPORTANT: All the following 3 members do not take multi-view into account.
   * They only count the number of input instances. The command generation shader must multiply
   * them by view_len to get the correct indices for resource ids.
   */

  /** Index of the first instances after sorting. */
  uint start;
  /** Total number of instances (including inverted facing). Needed to issue the draw call. */
  uint len;
  /** Number of non inverted scaling instances in this Group. */
  uint front_facing_len;

  /** #gpu::Batch values to be copied to #DrawCommand after sorting (if not overridden). */
  int vertex_len;
  int vertex_first;
  int base_index;

  /** Atomic counters used during command sorting. GPU only. Reset on CPU. */

  /* Counts visible and invisble instances. Create drawcalls when it reaches `DrawGroup::len`. */
  uint total_counter;
  /* Counts only visible instance (counting multi-view). Used to issue the drawcalls. */

#ifndef GPU_SHADER

  /* NOTE: Union just to make sure the struct has always the same size on all platform. */
  union {
    struct {
      /** For debug printing only. */
      uint front_proto_len;
      uint back_proto_len;
      /** Needed to create the correct draw call. */
      gpu::Batch *gpu_batch;
#  ifdef WITH_METAL_BACKEND
      GPUShader *gpu_shader;
#  endif
    };
    struct {
#endif
      uint front_facing_counter;
      uint back_facing_counter;
      uint _pad0, _pad1;
#if defined(WITH_METAL_BACKEND) || defined(GPU_METAL)
      uint _pad2, _pad3, _pad4, _pad5;
#endif
#ifndef GPU_SHADER
    };
  };
#endif
};
BLI_STATIC_ASSERT_ALIGN(DrawGroup, 16)

/**
 * Representation of a future draw call inside a DrawGroup. This #DrawPrototype is then
 * converted into #DrawCommand on GPU after visibility and compaction. Multiple
 * #DrawPrototype might get merged into the same final #DrawCommand.
 */
struct DrawPrototype {
  /* Reference to parent DrawGroup to get the gpu::Batch vertex / instance count. */
  uint group_id;
  /* Resource handle associated with this call. Also reference visibility. */
  uint resource_handle;
  /* Custom extra value to be used by the engines. */
  uint custom_id;
  /* Number of instances. */
  uint instance_len;
};
BLI_STATIC_ASSERT_ALIGN(DrawPrototype, 16)

/** \} */

#ifndef GPU_SHADER
};  // namespace blender::draw::command
#endif
