Commits (123)
......@@ -410,13 +410,13 @@ debian/x86_test-gl:
variables:
FDO_DISTRIBUTION_EXEC: 'env KERNEL_URL=${KERNEL_URL} FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/container/${CI_JOB_NAME}.sh'
KERNEL_URL: &kernel-rootfs-url "https://gitlab.freedesktop.org/gfx-ci/linux/-/archive/v5.13-rc5-for-mesa-ci-2bb5d9ffd79c/linux-v5.13-rc5-for-mesa-ci-2bb5d9ffd79c.tar.bz2"
MESA_IMAGE_TAG: &debian-x86_test-gl "2021-09-01-piglit"
MESA_IMAGE_TAG: &debian-x86_test-gl "2021-2021-10-07-piglit"
# Debian 11 based x86 test image for VK
debian/x86_test-vk:
extends: .use-debian/x86_test-base
variables:
MESA_IMAGE_TAG: &debian-x86_test-vk "2021-09-01-piglit"
MESA_IMAGE_TAG: &debian-x86_test-vk "2021-2021-10-07-piglit"
# Debian 11 based ARM build image
debian/arm_build:
......@@ -465,7 +465,7 @@ fedora/x86_build:
variables:
GIT_STRATEGY: fetch
KERNEL_URL: *kernel-rootfs-url
MESA_ROOTFS_TAG: &kernel-rootfs "2021-10-01-amlogic-kms"
MESA_ROOTFS_TAG: &kernel-rootfs "2021-10-07-piglit"
DISTRIBUTION_TAG: &distribution-tag-arm "${MESA_ROOTFS_TAG}--${MESA_ARTIFACTS_TAG}--${MESA_TEMPLATES_COMMIT}"
script:
- .gitlab-ci/container/lava_build.sh
......@@ -519,7 +519,7 @@ debian/arm_test:
FDO_DISTRIBUTION_EXEC: 'env ARTIFACTS_PREFIX=https://${MINIO_HOST}/mesa-lava ARTIFACTS_SUFFIX=${MESA_ROOTFS_TAG}--${MESA_ARM_BUILD_TAG}--${MESA_TEMPLATES_COMMIT} CI_PROJECT_PATH=${CI_PROJECT_PATH} FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} FDO_UPSTREAM_REPO=${FDO_UPSTREAM_REPO} bash .gitlab-ci/container/${CI_JOB_NAME}.sh'
FDO_DISTRIBUTION_TAG: "${MESA_IMAGE_TAG}--${MESA_ROOTFS_TAG}--${MESA_ARM_BUILD_TAG}--${MESA_TEMPLATES_COMMIT}"
MESA_ARM_BUILD_TAG: *debian-arm_build
MESA_IMAGE_TAG: &debian-arm_test "2021-09-11-etnaviv"
MESA_IMAGE_TAG: &debian-arm_test "2021-09-17-deqp"
MESA_ROOTFS_TAG: *kernel-rootfs
.use-debian/arm_test:
......
......@@ -6,7 +6,7 @@ git config --global user.email "mesa@example.com"
git config --global user.name "Mesa CI"
git clone \
https://github.com/KhronosGroup/VK-GL-CTS.git \
-b vulkan-cts-1.2.7.0 \
-b vulkan-cts-1.2.7.1 \
--depth 1 \
/VK-GL-CTS
pushd /VK-GL-CTS
......
......@@ -4,7 +4,7 @@ set -ex
git clone https://gitlab.freedesktop.org/mesa/piglit.git --single-branch --no-checkout /piglit
pushd /piglit
git checkout 99be1b06ff360edc17e9117bd82189dbade42013
git checkout 7d7dd2688c214e1b3c00f37226500cbec4a58efb
patch -p1 <$OLDPWD/.gitlab-ci/piglit/disable-vs_in.diff
cmake -S . -B . -G Ninja -DCMAKE_BUILD_TYPE=Release $PIGLIT_OPTS $EXTRA_CMAKE_ARGS
ninja $PIGLIT_BUILD_TARGETS
......
......@@ -9,7 +9,7 @@ Write-Host "Compiling Mesa"
$builddir = New-Item -ItemType Directory -Name "_build"
$installdir = New-Item -ItemType Directory -Name "_install"
Push-Location $builddir.FullName
cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=amd64 && meson --default-library=shared -Dzlib:default_library=static --buildtype=release -Db_ndebug=false -Dc_std=c17 -Dcpp_std=vc++latest -Db_vscrt=mt --cmake-prefix-path=`"C:\llvm-10`" --pkg-config-path=`"C:\llvm-10\lib\pkgconfig;C:\llvm-10\share\pkgconfig;C:\spirv-tools\lib\pkgconfig`" --prefix=`"$installdir`" -Dllvm=enabled -Dshared-llvm=disabled -Dvulkan-drivers=swrast,amd -Dgallium-drivers=swrast,d3d12,zink -Dosmesa=true -Dshared-glapi=enabled -Dgles2=enabled -Dmicrosoft-clc=enabled -Dstatic-libclc=all -Dspirv-to-dxil=true -Dbuild-tests=true -Dwerror=true -Dwarning_level=2 -Dzlib:warning_level=1 -Dlibelf:warning_level=1 && ninja -j32 install && meson test --num-processes 32"
cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=amd64 && meson --default-library=shared -Dzlib:default_library=static --buildtype=release -Db_ndebug=false -Dc_std=c17 -Dcpp_std=vc++latest -Db_vscrt=mt --cmake-prefix-path=`"C:\llvm-10`" --pkg-config-path=`"C:\llvm-10\lib\pkgconfig;C:\llvm-10\share\pkgconfig;C:\spirv-tools\lib\pkgconfig`" --prefix=`"$installdir`" -Dllvm=enabled -Dshared-llvm=disabled -Dvulkan-drivers=swrast,amd -Dgallium-drivers=swrast,d3d12,zink -Dshared-glapi=enabled -Dgles2=enabled -Dmicrosoft-clc=enabled -Dstatic-libclc=all -Dspirv-to-dxil=true -Dbuild-tests=true -Dwerror=true -Dwarning_level=2 -Dzlib:warning_level=1 -Dlibelf:warning_level=1 && ninja -j32 install && meson test --num-processes 32"
$buildstatus = $?
Pop-Location
......
21.3.0-devel
22.0.0-devel
......@@ -670,6 +670,8 @@ RADV driver environment variables
disable VRS for flat shading (only on GFX10.3+)
``preoptir``
dump LLVM IR before any optimizations
``prologs``
dump vertex shader prologs
``shaders``
dump shaders
``shaderstats``
......
......@@ -497,7 +497,7 @@ Khronos extensions that are not part of any Vulkan version:
VK_KHR_shader_terminate_invocation DONE (anv, radv, tu)
VK_KHR_shared_presentable_image not started
VK_KHR_surface DONE (anv, lvp, radv, tu, v3dv, vn)
VK_KHR_surface_protected_capabilities DONE (anv, lvp, radv, vn)
VK_KHR_surface_protected_capabilities DONE (anv, lvp, radv, v3dv, vn)
VK_KHR_swapchain DONE (anv, lvp, radv, tu, v3dv, vn)
VK_KHR_swapchain_mutable_format DONE (anv, radv, vn)
VK_KHR_wayland_surface DONE (anv, lvp, radv, tu, v3dv, vn)
......@@ -529,7 +529,7 @@ Khronos extensions that are not part of any Vulkan version:
VK_EXT_image_robustness DONE (anv, radv)
VK_EXT_index_type_uint8 DONE (anv, lvp, radv/gfx8+, v3dv, tu)
VK_EXT_inline_uniform_block DONE (anv, radv)
VK_EXT_line_rasterization DONE (anv, lvp, radv)
VK_EXT_line_rasterization DONE (anv, lvp, radv, tu)
VK_EXT_memory_budget DONE (anv, radv, tu)
VK_EXT_memory_priority DONE (radv)
VK_EXT_multi_draw DONE (anv, lvp, radv)
......@@ -554,7 +554,7 @@ Khronos extensions that are not part of any Vulkan version:
VK_EXT_texel_buffer_alignment DONE (anv, radv)
VK_EXT_transform_feedback DONE (anv, lvp, radv, tu, vn)
VK_EXT_vertex_attribute_divisor DONE (anv, radv, lvp, tu, v3dv)
VK_EXT_vertex_input_dynamic_state DONE (lvp)
VK_EXT_vertex_input_dynamic_state DONE (lvp, radv)
VK_EXT_ycbcr_image_arrays DONE (anv, radv)
VK_ANDROID_external_memory_android_hardware_buffer DONE (anv, radv, vn)
VK_ANDROID_native_buffer DONE (anv, radv, vn)
......
VK_EXT_color_write_enable on lavapipe
GL_ARB_texture_filter_anisotropic in llvmpipe
Anisotropic texture filtering in lavapipe
VK_EXT_shader_atomic_float2 on Intel and RADV.
VK_KHR_timeline_semaphore on lavapipe
VK_EXT_external_memory_host on lavapipe
GL_AMD_pinned_memory on llvmpipe
GL 4.5 compatibility on llvmpipe
VK_EXT_primitive_topology_list_restart on RADV and lavapipe.
ES 3.2 on zink
VK_KHR_depth_stencil_resolve on lavapipe
VK_KHR_shader_integer_dot_product on RADV.
OpenGL FP16 support on llvmpipe
VK_KHR_shader_float16_int8 on lavapipe
VK_KHR_shader_subgroup_extended_types on lavapipe
VK_KHR_spirv_1_4 on lavapipe
Experimental raytracing support on RADV
VK_KHR_synchronization2 on Intel
NGG shader based culling is now enabled by default on GFX10.3 on RADV.
VK_KHR_maintenance4 on RADV
......@@ -14,12 +14,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.khronos.org/registry/egl
**
** Khronos $Git commit SHA1: e8baa0bf39 $ on $Git commit date: 2021-04-26 17:56:26 -0600 $
** Khronos $Git commit SHA1: dc0b58dca5 $ on $Git commit date: 2021-06-25 01:58:50 +0200 $
*/
#include <EGL/eglplatform.h>
#define EGL_EGLEXT_VERSION 20210604
#define EGL_EGLEXT_VERSION 20210629
/* Generated C header for:
* API: egl
......@@ -651,6 +651,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSwapPolicyEXT (EGLint external_win_id
#endif
#endif /* EGL_EXT_compositor */
#ifndef EGL_EXT_config_select_group
#define EGL_EXT_config_select_group 1
#define EGL_CONFIG_SELECT_GROUP_EXT 0x34C0
#endif /* EGL_EXT_config_select_group */
#ifndef EGL_EXT_create_context_robustness
#define EGL_EXT_create_context_robustness 1
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
......@@ -702,6 +707,10 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
#define EGL_DEVICE_UUID_EXT 0x335C
#define EGL_DRIVER_UUID_EXT 0x335D
#define EGL_DRIVER_NAME_EXT 0x335E
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEBINARYEXTPROC) (EGLDeviceEXT device, EGLint name, EGLint max_size, void *value, EGLint *size);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceBinaryEXT (EGLDeviceEXT device, EGLint name, EGLint max_size, void *value, EGLint *size);
#endif
#endif /* EGL_EXT_device_persistent_id */
#ifndef EGL_EXT_device_query
......@@ -895,6 +904,11 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy,
#define EGL_PLATFORM_XCB_SCREEN_EXT 0x31DE
#endif /* EGL_EXT_platform_xcb */
#ifndef EGL_EXT_present_opaque
#define EGL_EXT_present_opaque 1
#define EGL_PRESENT_OPAQUE_EXT 0x31DF
#endif /* EGL_EXT_present_opaque */
#ifndef EGL_EXT_protected_content
#define EGL_EXT_protected_content 1
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
......
......@@ -75,7 +75,14 @@ cull_face(nir_builder *b, nir_ssa_def *pos[3][4], const position_w_info *w_info)
nir_ssa_def *cull_front = nir_build_load_cull_front_face_enabled_amd(b);
nir_ssa_def *cull_back = nir_build_load_cull_back_face_enabled_amd(b);
return nir_inot(b, nir_bcsel(b, front_facing, cull_front, cull_back));
nir_ssa_def *face_culled = nir_bcsel(b, front_facing, cull_front, cull_back);
/* Don't reject NaN and +/-infinity, these are tricky.
* Just trust fixed-function HW to handle these cases correctly.
*/
face_culled = nir_iand(b, face_culled, nir_fisfinite(b, det));
return nir_inot(b, face_culled);
}
static nir_ssa_def *
......
......@@ -730,6 +730,12 @@ compact_vertices_after_culling(nir_builder *b,
nir_store_var(b, repacked_arg_vars[i], arg_val, 0x1u);
}
}
nir_push_else(b, if_packed_es_thread);
{
nir_store_var(b, position_value_var, nir_ssa_undef(b, 4, 32), 0xfu);
for (unsigned i = 0; i < max_exported_args; ++i)
nir_store_var(b, repacked_arg_vars[i], nir_ssa_undef(b, 1, 32), 0x1u);
}
nir_pop_if(b, if_packed_es_thread);
nir_if *if_gs_accepted = nir_push_if(b, nir_load_var(b, gs_accepted_var));
......
......@@ -461,6 +461,13 @@ static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
/* RGP gets very confused if these clocks are 0. The 1 GHz clocks are not necessarily correct,
* but the resulting traces are at least somewhat useful. */
if (!chunk->trace_shader_core_clock)
chunk->trace_shader_core_clock = 1e9;
if (!chunk->trace_memory_clock)
chunk->trace_memory_clock = 1e9;
chunk->device_id = rad_info->pci_id;
chunk->device_revision_id = rad_info->pci_rev_id;
chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd * (has_wave32 ? 2 : 1);
......
......@@ -1477,6 +1477,10 @@ static bool gfx10_DCN_requires_independent_64B_blocks(const struct radeon_info *
{
assert(info->chip_class >= GFX10);
/* Older kernels have buggy DAL. */
if (info->drm_minor <= 43)
return true;
/* For 4K, DCN requires INDEPENDENT_64B_BLOCKS = 1 and MAX_COMPRESSED_BLOCK_SIZE = 64B. */
return config->info.width > 2560 || config->info.height > 2560;
}
......@@ -1519,6 +1523,10 @@ static bool is_dcc_supported_by_DCN(const struct radeon_info *info,
if (info->use_display_dcc_unaligned && (rb_aligned || pipe_aligned))
return false;
/* Big resolutions don't support DCC. */
if (config->info.width > 5760 || config->info.height > 5760)
return false;
switch (info->chip_class) {
case GFX9:
/* There are more constraints, but we always set
......@@ -2161,8 +2169,13 @@ static int gfx9_compute_surface(struct ac_addrlib *addrlib, const struct radeon_
surf->u.gfx9.color.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
}
/* Use 64 && 128 for the non-modifier path for compatibility. */
if (info->chip_class >= GFX10_3) {
if ((info->chip_class >= GFX10_3 && info->family <= CHIP_YELLOW_CARP) ||
/* Newer chips will skip this when possible to get better performance.
* This is also possible for other gfx10.3 chips, but is disabled for
* interoperability between different Mesa versions.
*/
(info->family > CHIP_YELLOW_CARP &&
gfx10_DCN_requires_independent_64B_blocks(info, config))) {
surf->u.gfx9.color.dcc.independent_64B_blocks = 1;
surf->u.gfx9.color.dcc.independent_128B_blocks = 1;
surf->u.gfx9.color.dcc.max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
......
......@@ -432,7 +432,7 @@ public:
}
Result vadd32(Definition dst, Op a, Op b, bool carry_out=false, Op carry_in=Op(Operand(s2)), bool post_ra=false) {
if (!b.op.isTemp() || b.op.regClass().type() != RegType::vgpr)
if (b.op.isConstant() || b.op.regClass().type() != RegType::vgpr)
std::swap(a, b);
if (!post_ra && (!b.op.hasRegClass() || b.op.regClass().type() == RegType::sgpr))
b = copy(def(v1), b);
......
......@@ -770,6 +770,13 @@ insert_wait_states(Program* program)
std::stack<unsigned, std::vector<unsigned>> loop_header_indices;
unsigned loop_progress = 0;
if (program->stage.has(SWStage::VS) && program->info->vs.dynamic_inputs) {
for (Definition def : program->vs_inputs) {
update_counters(in_ctx[0], event_vmem);
insert_wait_entry(in_ctx[0], def, event_vmem);
}
}
for (unsigned i = 0; i < program->blocks.size();) {
Block& current = program->blocks[i++];
wait_ctx ctx = in_ctx[current.index];
......
......@@ -247,10 +247,10 @@ get_reg_class(isel_context* ctx, RegType type, unsigned components, unsigned bit
}
void
setup_vs_output_info(isel_context* ctx, nir_shader* nir, bool export_prim_id,
bool export_clip_dists, const radv_vs_output_info* outinfo)
setup_vs_output_info(isel_context* ctx, nir_shader* nir,
const radv_vs_output_info* outinfo)
{
ctx->export_clip_dists = export_clip_dists;
ctx->export_clip_dists = outinfo->export_clip_dists;
ctx->num_clip_distances = util_bitcount(outinfo->clip_dist_mask);
ctx->num_cull_distances = util_bitcount(outinfo->cull_dist_mask);
......@@ -269,8 +269,7 @@ void
setup_vs_variables(isel_context* ctx, nir_shader* nir)
{
if (ctx->stage == vertex_vs || ctx->stage == vertex_ngg) {
const radv_vs_output_info* outinfo = &ctx->program->info->vs.outinfo;
setup_vs_output_info(ctx, nir, outinfo->export_prim_id, outinfo->export_clip_dists, outinfo);
setup_vs_output_info(ctx, nir, &ctx->program->info->vs.outinfo);
/* TODO: NGG streamout */
if (ctx->stage.hw == HWStage::NGG)
......@@ -292,8 +291,7 @@ setup_gs_variables(isel_context* ctx, nir_shader* nir)
ctx->program->config->lds_size =
ctx->program->info->gs_ring_info.lds_size; /* Already in units of the alloc granularity */
} else if (ctx->stage == vertex_geometry_ngg || ctx->stage == tess_eval_geometry_ngg) {
const radv_vs_output_info* outinfo = &ctx->program->info->vs.outinfo;
setup_vs_output_info(ctx, nir, false, outinfo->export_clip_dists, outinfo);
setup_vs_output_info(ctx, nir, &ctx->program->info->vs.outinfo);
ctx->program->config->lds_size =
DIV_ROUND_UP(nir->info.shared_size, ctx->program->dev.lds_encoding_granule);
......@@ -315,8 +313,7 @@ setup_tes_variables(isel_context* ctx, nir_shader* nir)
ctx->tcs_num_patches = ctx->args->shader_info->num_tess_patches;
if (ctx->stage == tess_eval_vs || ctx->stage == tess_eval_ngg) {
const radv_vs_output_info* outinfo = &ctx->program->info->tes.outinfo;
setup_vs_output_info(ctx, nir, outinfo->export_prim_id, outinfo->export_clip_dists, outinfo);
setup_vs_output_info(ctx, nir, &ctx->program->info->tes.outinfo);
/* TODO: NGG streamout */
if (ctx->stage.hw == HWStage::NGG)
......@@ -631,7 +628,6 @@ init_context(isel_context* ctx, nir_shader* shader)
case nir_intrinsic_load_frag_coord:
case nir_intrinsic_load_frag_shading_rate:
case nir_intrinsic_load_sample_pos:
case nir_intrinsic_load_layer_id:
case nir_intrinsic_load_local_invocation_id:
case nir_intrinsic_load_local_invocation_index:
case nir_intrinsic_load_subgroup_invocation:
......@@ -901,9 +897,7 @@ setup_isel_context(Program* program, unsigned shader_count, struct nir_shader* c
unsigned scratch_size = 0;
if (program->stage == gs_copy_vs) {
assert(shader_count == 1);
setup_vs_output_info(&ctx, shaders[0], false,
args->shader_info->vs.outinfo.export_clip_dists,
&args->shader_info->vs.outinfo);
setup_vs_output_info(&ctx, shaders[0], &args->shader_info->vs.outinfo);
} else {
for (unsigned i = 0; i < shader_count; i++) {
nir_shader* nir = shaders[i];
......
......@@ -263,3 +263,47 @@ aco_compile_shader(unsigned shader_count, struct nir_shader* const* shaders,
*binary = (radv_shader_binary*)legacy_binary;
}
void
aco_compile_vs_prolog(const struct radv_vs_prolog_key* key, struct radv_prolog_binary** binary,
const struct radv_shader_args* args)
{
aco::init();
/* create program */
ac_shader_config config = {0};
std::unique_ptr<aco::Program> program{new aco::Program};
program->collect_statistics = false;
program->debug.func = NULL;
program->debug.private_data = NULL;
/* create IR */
unsigned num_preserved_sgprs;
aco::select_vs_prolog(program.get(), key, &config, args, &num_preserved_sgprs);
aco::insert_NOPs(program.get());
if (args->options->dump_shader)
aco_print_program(program.get(), stderr);
/* assembly */
std::vector<uint32_t> code;
code.reserve(align(program->blocks[0].instructions.size() * 2, 16));
unsigned exec_size = aco::emit_program(program.get(), code);
if (args->options->dump_shader) {
aco::print_asm(program.get(), code, exec_size / 4u, stderr);
fprintf(stderr, "\n");
}
/* copy into binary */
size_t size = code.size() * sizeof(uint32_t) + sizeof(radv_prolog_binary);
radv_prolog_binary* prolog_binary = (radv_prolog_binary*)calloc(size, 1);
prolog_binary->num_sgprs = config.num_sgprs;
prolog_binary->num_vgprs = config.num_vgprs;
prolog_binary->num_preserved_sgprs = num_preserved_sgprs;
prolog_binary->code_size = code.size() * sizeof(uint32_t);
memcpy(prolog_binary->data, code.data(), prolog_binary->code_size);
*binary = prolog_binary;
}
......@@ -44,6 +44,9 @@ extern const struct aco_compiler_statistic_info* aco_statistic_infos;
void aco_compile_shader(unsigned shader_count, struct nir_shader* const* shaders,
struct radv_shader_binary** binary, const struct radv_shader_args* args);
void aco_compile_vs_prolog(const struct radv_vs_prolog_key* key, struct radv_prolog_binary** binary,
const struct radv_shader_args* args);
#ifdef __cplusplus
}
#endif
......
......@@ -38,6 +38,7 @@
struct radv_shader_args;
struct radv_shader_info;
struct radv_vs_prolog_key;
namespace aco {
......@@ -2072,6 +2073,8 @@ public:
unsigned next_divergent_if_logical_depth = 0;
unsigned next_uniform_if_depth = 0;
std::vector<Definition> vs_inputs;
struct {
FILE* output = stderr;
bool shorten_messages = false;
......@@ -2145,6 +2148,9 @@ void select_gs_copy_shader(Program* program, struct nir_shader* gs_shader, ac_sh
const struct radv_shader_args* args);
void select_trap_handler_shader(Program* program, struct nir_shader* shader,
ac_shader_config* config, const struct radv_shader_args* args);
void select_vs_prolog(Program* program, const struct radv_vs_prolog_key* key,
ac_shader_config* config, const struct radv_shader_args* args,
unsigned* num_preserved_sgprs);
void lower_phis(Program* program);
void calc_min_waves(Program* program);
......