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

#ifdef GPU_SHADER
#  pragma once
#  include "gpu_shader_compat.hh"

#  include "draw_object_infos_infos.hh"
#  include "draw_view_infos.hh"
#  include "eevee_common_infos.hh"
#  include "eevee_debug_shared.hh"
#  include "eevee_fullscreen_infos.hh"
#  include "eevee_light_infos.hh"
#  include "eevee_lightprobe_infos.hh"
#  include "eevee_sampling_infos.hh"
#  include "eevee_shadow_infos.hh"
#  include "eevee_shadow_shared.hh"
#  include "eevee_uniform_infos.hh"
#endif

#ifdef GLSL_CPP_STUBS
#  define SPHERE_PROBE
#endif

#include "draw_defines.hh"
#include "eevee_defines.hh"

#include "gpu_shader_create_info.hh"

/* -------------------------------------------------------------------- */
/** \name Shadow pipeline
 * \{ */

GPU_SHADER_CREATE_INFO(eevee_shadow_clipmap_clear)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_CLIPMAP_GROUP_SIZE)
STORAGE_BUF(0, write, ShadowTileMapClip, tilemaps_clip_buf[])
PUSH_CONSTANT(int, tilemaps_clip_buf_len)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_clipmap_clear_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_bounds)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_BOUNDS_GROUP_SIZE)
STORAGE_BUF(LIGHT_BUF_SLOT, read_write, LightData, light_buf[])
STORAGE_BUF(LIGHT_CULL_BUF_SLOT, read, LightCullingData, light_cull_buf)
STORAGE_BUF(4, read, uint, casters_id_buf[])
STORAGE_BUF(5, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(6, read, ObjectBounds, bounds_buf[])
STORAGE_BUF(7, read_write, ShadowTileMapClip, tilemaps_clip_buf[])
PUSH_CONSTANT(int, resource_len)
TYPEDEF_SOURCE("draw_shader_shared.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_tilemap_bounds_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_init)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
STORAGE_BUF(0, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(1, read_write, uint, tiles_buf[])
STORAGE_BUF(2, read_write, ShadowTileMapClip, tilemaps_clip_buf[])
STORAGE_BUF(4, read_write, uint2, pages_cached_buf[])
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_tilemap_init_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tag_update)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(1, 1, 1)
STORAGE_BUF(0, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(1, read_write, uint, tiles_buf[])
STORAGE_BUF(5, read, ObjectBounds, bounds_buf[])
STORAGE_BUF(6, read, uint, resource_ids_buf[])
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
COMPUTE_SOURCE("eevee_shadow_tag_update_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_opaque)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_DEPTH_SCAN_GROUP_SIZE, SHADOW_DEPTH_SCAN_GROUP_SIZE)
STORAGE_BUF(5, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(6, read_write, uint, tiles_buf[])
PUSH_CONSTANT(int2, input_depth_extent)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
TYPEDEF_SOURCE("eevee_lightprobe_shared.hh")
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
ADDITIONAL_INFO(eevee_hiz_data)
ADDITIONAL_INFO(eevee_light_data)
COMPUTE_SOURCE("eevee_shadow_tag_usage_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_surfels)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SURFEL_GROUP_SIZE)
STORAGE_BUF(6, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(7, read_write, uint, tiles_buf[])
PUSH_CONSTANT(int, directional_level)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
TYPEDEF_SOURCE("eevee_lightprobe_shared.hh")
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
ADDITIONAL_INFO(eevee_light_data)
ADDITIONAL_INFO(eevee_global_ubo)
ADDITIONAL_INFO(eevee_surfel_common)
COMPUTE_SOURCE("eevee_shadow_tag_usage_surfels_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_NAMED_INTERFACE_INFO(eevee_shadow_tag_transparent_iface, interp)
SMOOTH(float3, P)
SMOOTH(float3, vP)
GPU_SHADER_NAMED_INTERFACE_END(interp)
GPU_SHADER_NAMED_INTERFACE_INFO(eevee_shadow_tag_transparent_flat_iface, interp_flat)
FLAT(float3, ls_aabb_min)
FLAT(float3, ls_aabb_max)
GPU_SHADER_NAMED_INTERFACE_END(interp_flat)

GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_transparent)
DO_STATIC_COMPILATION()
VERTEX_IN(0, float3, pos)
STORAGE_BUF(4, read, ObjectBounds, bounds_buf[])
STORAGE_BUF(5, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(6, read_write, uint, tiles_buf[])
PUSH_CONSTANT(int2, fb_resolution)
PUSH_CONSTANT(int, fb_lod)
VERTEX_OUT(eevee_shadow_tag_transparent_iface)
VERTEX_OUT(eevee_shadow_tag_transparent_flat_iface)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
TYPEDEF_SOURCE("eevee_lightprobe_shared.hh")
ADDITIONAL_INFO(draw_resource_id_varying)
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
ADDITIONAL_INFO(draw_modelmat)
ADDITIONAL_INFO(eevee_hiz_data)
ADDITIONAL_INFO(eevee_light_data)
VERTEX_SOURCE("eevee_shadow_tag_usage_vert.glsl")
FRAGMENT_SOURCE("eevee_shadow_tag_usage_frag.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_volume)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(VOLUME_GROUP_SIZE, VOLUME_GROUP_SIZE, VOLUME_GROUP_SIZE)
STORAGE_BUF(4, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(5, read_write, uint, tiles_buf[])
ADDITIONAL_INFO(eevee_volume_properties_data)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
TYPEDEF_SOURCE("eevee_lightprobe_shared.hh")
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
ADDITIONAL_INFO(eevee_hiz_data)
ADDITIONAL_INFO(eevee_light_data)
ADDITIONAL_INFO(eevee_sampling_data)
COMPUTE_SOURCE("eevee_shadow_tag_usage_volume_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_page_mask)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
GROUP_SHARED(uint, tiles_local[SHADOW_TILEDATA_PER_TILEMAP])
GROUP_SHARED(uint, levels_rendered)
GROUP_SHARED(uint, force_base_page)
PUSH_CONSTANT(int, max_view_per_tilemap)
STORAGE_BUF(0, read_write, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(1, read_write, uint, tiles_buf[])
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_page_mask_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_finalize)
DO_STATIC_COMPILATION()
TYPEDEF_SOURCE("draw_shader_shared.hh")
LOCAL_GROUP_SIZE(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
STORAGE_BUF(0, read, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(1, read, uint, tiles_buf[])
STORAGE_BUF(2, read_write, ShadowPagesInfoData, pages_infos_buf)
STORAGE_BUF(3, read_write, ShadowStatistics, statistics_buf)
STORAGE_BUF(4, write, ViewMatrices, view_infos_buf[SHADOW_VIEW_MAX])
STORAGE_BUF(5, write, ShadowRenderView, render_view_buf[SHADOW_VIEW_MAX])
STORAGE_BUF(6, read, ShadowTileMapClip, tilemaps_clip_buf[])
IMAGE(0, UINT_32, write, uimage2D, tilemaps_img)
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_tilemap_finalize_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_rendermap)
DO_STATIC_COMPILATION()
TYPEDEF_SOURCE("draw_shader_shared.hh")
LOCAL_GROUP_SIZE(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
STORAGE_BUF(0, read_write, ShadowStatistics, statistics_buf)
STORAGE_BUF(1, read, ShadowRenderView, render_view_buf[SHADOW_VIEW_MAX])
STORAGE_BUF(2, read_write, uint, tiles_buf[])
STORAGE_BUF(3, read_write, DispatchCommand, clear_dispatch_buf)
STORAGE_BUF(4, read_write, DrawCommandArray, tile_draw_buf)
STORAGE_BUF(5, write, uint, dst_coord_buf[SHADOW_RENDER_MAP_SIZE])
STORAGE_BUF(6, write, uint, src_coord_buf[SHADOW_RENDER_MAP_SIZE])
STORAGE_BUF(7, write, uint, render_map_buf[SHADOW_RENDER_MAP_SIZE])
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_tilemap_rendermap_comp.glsl")
GPU_SHADER_CREATE_END()

GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_amend)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
IMAGE(0, UINT_32, read_write, uimage2D, tilemaps_img)
STORAGE_BUF(LIGHT_CULL_BUF_SLOT, read, LightCullingData, light_cull_buf)
STORAGE_BUF(LIGHT_BUF_SLOT, read_write, LightData, light_buf[])
/* The call bind_resources(lights) also uses LIGHT_ZBIN_BUF_SLOT and LIGHT_TILE_BUF_SLOT. */
STORAGE_BUF(4, read, ShadowTileMapData, tilemaps_buf[])
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
ADDITIONAL_INFO(draw_view)
COMPUTE_SOURCE("eevee_shadow_tilemap_amend_comp.glsl")
GPU_SHADER_CREATE_END()

/* AtomicMin clear implementation. */
GPU_SHADER_CREATE_INFO(eevee_shadow_page_clear)
DO_STATIC_COMPILATION()
LOCAL_GROUP_SIZE(SHADOW_PAGE_CLEAR_GROUP_SIZE, SHADOW_PAGE_CLEAR_GROUP_SIZE)
STORAGE_BUF(2, read, ShadowPagesInfoData, pages_infos_buf)
STORAGE_BUF(6, read, uint, dst_coord_buf[SHADOW_RENDER_MAP_SIZE])
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
COMPUTE_SOURCE("eevee_shadow_page_clear_comp.glsl")
IMAGE(SHADOW_ATLAS_IMG_SLOT, UINT_32, read_write, uimage2DArrayAtomic, shadow_atlas_img)
GPU_SHADER_CREATE_END()

/* TBDR clear implementation. */
GPU_SHADER_CREATE_INFO(eevee_shadow_page_tile_clear)
DO_STATIC_COMPILATION()
DEFINE("PASS_CLEAR")
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
BUILTINS(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER)
STORAGE_BUF(8, read, uint, src_coord_buf[SHADOW_RENDER_MAP_SIZE])
VERTEX_SOURCE("eevee_shadow_page_tile_vert.glsl")
FRAGMENT_SOURCE("eevee_shadow_page_tile_frag.glsl")
FRAGMENT_OUT_ROG(0, float, out_tile_depth, SHADOW_ROG_ID)
GPU_SHADER_CREATE_END()

/* Interface for passing precalculated values in accumulation vertex to frag. */
GPU_SHADER_NAMED_INTERFACE_INFO(eevee_shadow_page_tile_store_noperspective_iface,
                                interp_noperspective)
NO_PERSPECTIVE(float2, out_texel_xy)
GPU_SHADER_NAMED_INTERFACE_END(interp_noperspective)
GPU_SHADER_NAMED_INTERFACE_INFO(eevee_shadow_page_tile_store_flat_iface, interp_flat)
#ifdef APPLE
/* Metal supports ushort which saves a bit of performance here. */
FLAT(ushort, out_page_z)
#else
FLAT(uint, out_page_z)
#endif
GPU_SHADER_NAMED_INTERFACE_END(interp_flat)

/* 2nd tile pass to store shadow depths in atlas. */
GPU_SHADER_CREATE_INFO(eevee_shadow_page_tile_store)
DO_STATIC_COMPILATION()
DEFINE("PASS_DEPTH_STORE")
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
BUILTINS(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER)
STORAGE_BUF(7, read, uint, dst_coord_buf[SHADOW_RENDER_MAP_SIZE])
STORAGE_BUF(8, read, uint, src_coord_buf[SHADOW_RENDER_MAP_SIZE])
SUBPASS_IN(0, float, Float2DArray, in_tile_depth, SHADOW_ROG_ID)
IMAGE(SHADOW_ATLAS_IMG_SLOT, UINT_32, read_write, uimage2DArray, shadow_atlas_img)
VERTEX_OUT(eevee_shadow_page_tile_store_noperspective_iface)
VERTEX_OUT(eevee_shadow_page_tile_store_flat_iface)
VERTEX_SOURCE("eevee_shadow_page_tile_vert.glsl")
FRAGMENT_SOURCE("eevee_shadow_page_tile_frag.glsl")
GPU_SHADER_CREATE_END()

/* Custom visibility check pass. */
GPU_SHADER_CREATE_INFO(eevee_shadow_view_visibility)
DO_STATIC_COMPILATION()
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
LOCAL_GROUP_SIZE(DRW_VISIBILITY_GROUP_SIZE)
DEFINE_VALUE("DRW_VIEW_LEN", STRINGIFY(DRW_VIEW_MAX))
STORAGE_BUF(0, read, ObjectBounds, bounds_buf[])
STORAGE_BUF(1, read_write, uint, visibility_buf[])
STORAGE_BUF(2, read, ShadowRenderView, render_view_buf[SHADOW_VIEW_MAX])
PUSH_CONSTANT(int, resource_len)
PUSH_CONSTANT(int, view_len)
PUSH_CONSTANT(int, visibility_word_per_draw)
COMPUTE_SOURCE("eevee_shadow_visibility_comp.glsl")
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(draw_view_culling)
ADDITIONAL_INFO(draw_object_infos)
GPU_SHADER_CREATE_END()

/** \} */

/* -------------------------------------------------------------------- */
/** \name Debug
 * \{ */

GPU_SHADER_CREATE_INFO(eevee_shadow_debug)
DO_STATIC_COMPILATION()
TYPEDEF_SOURCE("eevee_defines.hh")
TYPEDEF_SOURCE("eevee_debug_shared.hh")
TYPEDEF_SOURCE("eevee_shadow_shared.hh")
STORAGE_BUF(5, read, ShadowTileMapData, tilemaps_buf[])
STORAGE_BUF(6, read, uint, tiles_buf[])
FRAGMENT_OUT_DUAL(0, float4, out_color_add, SRC_0)
FRAGMENT_OUT_DUAL(0, float4, out_color_mul, SRC_1)
PUSH_CONSTANT(int, debug_mode)
PUSH_CONSTANT(int, debug_tilemap_index)
DEPTH_WRITE(DepthWrite::ANY)
FRAGMENT_SOURCE("eevee_shadow_debug_frag.glsl")
ADDITIONAL_INFO(eevee_fullscreen)
ADDITIONAL_INFO(draw_view)
ADDITIONAL_INFO(eevee_hiz_data)
ADDITIONAL_INFO(eevee_light_data)
ADDITIONAL_INFO(eevee_shadow_data)
GPU_SHADER_CREATE_END()

/** \} */
