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


# Recipe for Skia skpbench.


import calendar


DEPS = [
  'flavor',
  'recipe_engine/context',
  'recipe_engine/file',
  'recipe_engine/path',
  'recipe_engine/platform',
  'recipe_engine/properties',
  'recipe_engine/python',
  'recipe_engine/raw_io',
  'recipe_engine/step',
  'recipe_engine/time',
  'run',
  'vars',
]

ADB_BINARY = 'adb.1.0.35'


def _run(api, title, *cmd, **kwargs):
  with api.context(cwd=api.path['start_dir'].join('skia')):
    return api.run(api.step, title, cmd=list(cmd), **kwargs)


def _adb(api, title, *cmd, **kwargs):
  if 'infra_step' not in kwargs:
    kwargs['infra_step'] = True
  return _run(api, title, ADB_BINARY, *cmd, **kwargs)


def skpbench_steps(api):
  """benchmark Skia using skpbench."""
  is_vulkan = 'Vulkan' in api.vars.builder_name
  is_android = 'Android' in api.vars.builder_name
  is_ccpr = 'CCPR' in api.vars.builder_name
  is_all_paths_volatile = 'AllPathsVolatile' in api.vars.builder_name
  is_mskp = 'Mskp' in api.vars.builder_name
  is_ddl = 'DDL' in api.vars.builder_name
  is_9x9 = '9x9' in api.vars.builder_name
  is_reduce_ops_task_splitting = 'ReduceOpsTaskSplitting' in api.vars.builder_name

  api.file.ensure_directory(
      'makedirs perf_dir', api.flavor.host_dirs.perf_data_dir)

  if is_android:
    app = api.vars.build_dir.join('skpbench')
    _adb(api, 'push skpbench', 'push', app, api.flavor.device_dirs.bin_dir)

  skpbench_dir = api.vars.workdir.join('skia', 'tools', 'skpbench')
  table = api.path.join(api.vars.swarming_out_dir, 'table')

  config = 'vk' if is_vulkan else 'gles' if is_android else 'gl'
  internal_samples = 4 if is_android else 8

  if is_all_paths_volatile:
    config = "%smsaa%i" % (config, internal_samples)

  skpbench_invocation = api.path.join(api.flavor.device_dirs.bin_dir, 'skpbench')

  # skbug.com/10184
  if is_vulkan and 'GalaxyS20' in api.vars.builder_name:
    skpbench_invocation = "LD_LIBRARY_PATH=/data/local/tmp %s" % skpbench_invocation

  skpbench_args = [
        skpbench_invocation,
        '--resultsfile', table,
        '--config', config,
        '--internalSamples', str(internal_samples),
        # TODO(dogben): Track down what's causing bots to die.
        '-v5']
  if is_ddl:
    skpbench_args += ['--ddl']
    # disable the mask generation threads for simplicity's sake in DDL mode
    skpbench_args += ['--gpuThreads', '0']
  if is_9x9:
    skpbench_args += [
        '--ddlNumRecordingThreads', 9,
        '--ddlTilingWidthHeight', 3]
  if is_reduce_ops_task_splitting:
    skpbench_args += [
        '--reduceOpsTaskSplitting']
  if is_android:
    skpbench_args += [
        '--adb',
        '--adb_binary', ADB_BINARY]
  if is_ccpr:
    skpbench_args += [
        '--pr', 'ccpr', '--cc', '--nocache',
        api.path.join(api.flavor.device_dirs.skp_dir, 'desk_*svg.skp'),
        api.path.join(api.flavor.device_dirs.skp_dir, 'desk_chalkboard.skp')]
  elif is_mskp:
    skpbench_args += [api.flavor.device_dirs.mskp_dir]
  elif is_all_paths_volatile:
    skpbench_args += [
        # nvpr takes every path when enabled, which isn't always the best choice
        # for volatile paths.
        '--pr', '~nvpr',
        '--allPathsVolatile',
        '--suffix', "_volatile",
        api.path.join(api.flavor.device_dirs.skp_dir, 'desk_*svg.skp'),
        api.path.join(api.flavor.device_dirs.skp_dir, 'desk_chalkboard.skp')]
  else:
    skpbench_args += [api.flavor.device_dirs.skp_dir]

  api.run(api.python, 'skpbench',
      script=skpbench_dir.join('skpbench.py'),
      args=skpbench_args)

  skiaperf_args = [
    table,
    '--properties',
    'gitHash', api.properties['revision'],
  ]
  if api.vars.is_trybot:
    skiaperf_args.extend([
      'issue',    api.vars.issue,
      'patchset', api.vars.patchset,
      'patch_storage', api.vars.patch_storage,
    ])

  skiaperf_args.extend(['swarming_bot_id', api.vars.swarming_bot_id])
  skiaperf_args.extend(['swarming_task_id', api.vars.swarming_task_id])

  now = api.time.utcnow()
  ts = int(calendar.timegm(now.utctimetuple()))
  json_path = api.path.join(
      api.flavor.host_dirs.perf_data_dir,
      'skpbench_%s_%d.json' % (api.properties['revision'], ts))

  skiaperf_args.extend([
    '--outfile', json_path
  ])

  skiaperf_args.append('--key')
  for k in sorted(api.vars.builder_cfg.keys()):
    if not k in ['configuration', 'role', 'is_trybot']:
      skiaperf_args.extend([k, api.vars.builder_cfg[k]])

  api.run(api.python, 'Parse skpbench output into Perf json',
      script=skpbench_dir.join('skiaperf.py'),
      args=skiaperf_args)


def RunSteps(api):
  api.vars.setup()
  api.file.ensure_directory('makedirs tmp_dir', api.vars.tmp_dir)

  # The app_name passed to api.flavor.setup() is used to determine which app
  # to install on an attached device. That work is done in skpbench_steps, so
  # we pass None here.
  api.flavor.setup(None)

  try:
    mksp_mode = ('Mskp' in api.vars.builder_name)
    api.flavor.install(skps=not mksp_mode, mskps=mksp_mode)
    skpbench_steps(api)
  finally:
    api.flavor.cleanup_steps()
  api.run.check_failure()


TEST_BUILDERS = [
  ('Perf-Android-Clang-Pixel-GPU-Adreno530-arm64-Release-All-'
   'Android_Skpbench_Mskp'),
  ('Perf-Android-Clang-Pixel-GPU-Adreno530-arm64-Release-All-'
   'Android_CCPR_Skpbench'),
  ('Perf-Android-Clang-Pixel-GPU-Adreno530-arm64-Release-All-'
   'Android_ReduceOpsTaskSplitting_Skpbench'),
  ('Perf-Android-Clang-GalaxyS20-GPU-MaliG77-arm64-Release-All-'
   'Android_AllPathsVolatile_Skpbench'),
  ('Perf-Android-Clang-GalaxyS20-GPU-MaliG77-arm64-Release-All-'
   'Android_Vulkan_AllPathsVolatile_Skpbench'),
  'Perf-Win10-Clang-Golo-GPU-QuadroP400-x86_64-Release-All-Vulkan_Skpbench',
  ('Perf-Win10-Clang-Golo-GPU-QuadroP400-x86_64-Release-All-'
   'Vulkan_Skpbench_DDLTotal_9x9'),
  ('Perf-Win10-Clang-Golo-GPU-QuadroP400-x86_64-Release-All-'
   'AllPathsVolatile_Skpbench'),
]


def GenTests(api):
  for builder in TEST_BUILDERS:
    test = (
      api.test(builder) +
      api.properties(buildername=builder,
                     revision='abc123',
                     path_config='kitchen',
                     swarm_out_dir='[SWARM_OUT_DIR]') +
      api.path.exists(
          api.path['start_dir'].join('skia'),
          api.path['start_dir'].join('skia', 'infra', 'bots', 'assets',
                                     'skp', 'VERSION'),
      ) +
      api.step_data('get swarming bot id',
          stdout=api.raw_io.output('skia-bot-123')) +
      api.step_data('get swarming task id',
          stdout=api.raw_io.output('123456'))
    )
    if 'Win' in builder and not 'LenovoYogaC630' in builder:
      test += api.platform('win', 64)
    yield test

  b = ('Perf-Android-Clang-Pixel2XL-GPU-Adreno540-arm64-Release-All-'
       'Android_Vulkan_Skpbench')
  yield (
    api.test('trybot') +
    api.properties(buildername=b,
                   revision='abc123',
                   path_config='kitchen',
                   swarm_out_dir='[SWARM_OUT_DIR]') +
    api.path.exists(
        api.path['start_dir'].join('skia'),
        api.path['start_dir'].join('skia', 'infra', 'bots', 'assets',
                                   'skp', 'VERSION'),
    ) +
    api.step_data('get swarming bot id',
        stdout=api.raw_io.output('skia-bot-123')) +
    api.step_data('get swarming task id',
        stdout=api.raw_io.output('123456')) +
    api.properties(patch_storage='gerrit') +
    api.properties.tryserver(
        buildername=b,
        gerrit_project='skia',
        gerrit_url='https://skia-review.googlesource.com/',
    )
  )
