<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2020 <NAME>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include <algorithm>
#include <iterator>
#include "vk_core.h"
#include "vk_replay.h"
#include "vk_resources.h"

#include "driver/ihv/amd/amd_counters.h"
#include "driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-VK.h"
#include "strings/string_utils.h"

static uint32_t FromKHRCounter(GPUCounter counterID)
{
  return (uint32_t)counterID - (uint32_t)GPUCounter::FirstVulkanExtended;
}

static GPUCounter ToKHRCounter(uint32_t idx)
{
  return (GPUCounter)((uint32_t)GPUCounter::FirstVulkanExtended + idx);
}

static void GetKHRUnitDescription(const VkPerformanceCounterUnitKHR khrUnit, CounterUnit &unit,
                                  CompType &type, uint32_t &byteWidth)
{
  switch(khrUnit)
  {
    case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR:
      unit = CounterUnit::Percentage;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR:
      unit = CounterUnit::Seconds;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR:
      unit = CounterUnit::Bytes;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR:
      unit = CounterUnit::Ratio;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR:
      unit = CounterUnit::Cycles;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    default: RDCERR("Invalid performance counter unit %d", khrUnit);
  }
}

void VulkanReplay::convertKhrCounterResult(CounterResult &rdcResult,
                                           const VkPerformanceCounterResultKHR &khrResult,
                                           VkPerformanceCounterUnitKHR khrUnit,
                                           VkPerformanceCounterStorageKHR khrStorage)
{
  CounterUnit unit;
  CompType type;
  uint32_t byteWidth;
  GetKHRUnitDescription(khrUnit, unit, type, byteWidth);

  double value;

  // Convert everything to doubles.
  switch(khrStorage)
  {
    case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: rdcResult.value.u64 = khrResult.int32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: rdcResult.value.u64 = khrResult.uint32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: rdcResult.value.u64 = khrResult.int64; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: rdcResult.value.u64 = khrResult.uint64; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: rdcResult.value.d = khrResult.float32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: rdcResult.value.d = khrResult.float64; break;
    default: value = 0; RDCERR("Wrong counter storage type %d", khrStorage);
  }

  // Special case for time units, renderdoc only has a Seconds type.
  if(khrUnit == VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR)
  {
    RDCASSERT(type == CompType::Double);
    rdcResult.value.d /= 1000.0 * 1000.0 * 1000.0;
  }
}

rdcarray<GPUCounter> VulkanReplay::EnumerateCounters()
{
  rdcarray<GPUCounter> ret;

  VkPhysicalDeviceFeatures availableFeatures = m_pDriver->GetDeviceFeatures();

  ret.push_back(GPUCounter::EventGPUDuration);
  if(availableFeatures.pipelineStatisticsQuery)
  {
    ret.push_back(GPUCounter::InputVerticesRead);
    ret.push_back(GPUCounter::IAPrimitives);
    ret.push_back(GPUCounter::GSPrimitives);
    ret.push_back(GPUCounter::RasterizerInvocations);
    ret.push_back(GPUCounter::RasterizedPrimitives);
  }

  if(availableFeatures.occlusionQueryPrecise)
    ret.push_back(GPUCounter::SamplesPassed);

  if(availableFeatures.pipelineStatisticsQuery)
  {<commit_msg>Convert GPU Time counter correctly<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2020 <NAME>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include <algorithm>
#include <iterator>
#include "vk_core.h"
#include "vk_replay.h"
#include "vk_resources.h"

#include "driver/ihv/amd/amd_counters.h"
#include "driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-VK.h"
#include "strings/string_utils.h"

static uint32_t FromKHRCounter(GPUCounter counterID)
{
  return (uint32_t)counterID - (uint32_t)GPUCounter::FirstVulkanExtended;
}

static GPUCounter ToKHRCounter(uint32_t idx)
{
  return (GPUCounter)((uint32_t)GPUCounter::FirstVulkanExtended + idx);
}

static void GetKHRUnitDescription(const VkPerformanceCounterUnitKHR khrUnit, CounterUnit &unit,
                                  CompType &type, uint32_t &byteWidth)
{
  switch(khrUnit)
  {
    case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR:
      unit = CounterUnit::Percentage;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR:
      unit = CounterUnit::Seconds;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR:
      unit = CounterUnit::Bytes;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR:
      unit = CounterUnit::Ratio;
      type = CompType::Double;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR:
      unit = CounterUnit::Absolute;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR:
      unit = CounterUnit::Cycles;
      type = CompType::UInt;
      byteWidth = 8;
      return;
    default: RDCERR("Invalid performance counter unit %d", khrUnit);
  }
}

void VulkanReplay::convertKhrCounterResult(CounterResult &rdcResult,
                                           const VkPerformanceCounterResultKHR &khrResult,
                                           VkPerformanceCounterUnitKHR khrUnit,
                                           VkPerformanceCounterStorageKHR khrStorage)
{
  CounterUnit unit;
  CompType type;
  uint32_t byteWidth;
  GetKHRUnitDescription(khrUnit, unit, type, byteWidth);

  double value;

  // Convert everything to doubles.
  switch(khrStorage)
  {
    case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: rdcResult.value.u64 = khrResult.int32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: rdcResult.value.u64 = khrResult.uint32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: rdcResult.value.u64 = khrResult.int64; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: rdcResult.value.u64 = khrResult.uint64; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: rdcResult.value.d = khrResult.float32; break;
    case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: rdcResult.value.d = khrResult.float64; break;
    default: value = 0; RDCERR("Wrong counter storage type %d", khrStorage);
  }

  // Special case for time units, renderdoc only has a Seconds type.
  if(khrUnit == VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR)
  {
    RDCASSERT(type == CompType::Double);

    if((khrStorage == VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR) ||
       (khrStorage == VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR))
    {
      rdcResult.value.d = rdcResult.value.d / (1000.0 * 1000.0 * 1000.0);
    }
    else
    {
      rdcResult.value.d = (double)(rdcResult.value.u64) / (1000.0 * 1000.0 * 1000.0);
    }
  }
}

rdcarray<GPUCounter> VulkanReplay::EnumerateCounters()
{
  rdcarray<GPUCounter> ret;

  VkPhysicalDeviceFeatures availableFeatures = m_pDriver->GetDeviceFeatures();

  ret.push_back(GPUCounter::EventGPUDuration);
  if(availableFeatures.pipelineStatisticsQuery)
  {
    ret.push_back(GPUCounter::InputVerticesRead);
    ret.push_back(GPUCounter::IAPrimitives);
    ret.push_back(GPUCounter::GSPrimitives);
    ret.push_back(GPUCounter::RasterizerInvocations);
    ret.push_back(GPUCounter::RasterizedPrimitives);
  }

  if(availableFeatures.occlusionQueryPrecise)
    ret.push_back(GPUCounter::SamplesPassed);

  if(availableFeatures.pipelineStatisticsQuery)
  {
{'fraction_non_alphanumeric': 0.10657104736490994, 'fraction_numerical': 0.015260173448965977, 'mean_word_length': 3.8358870967741936, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '354188', 'n_tokens_mistral': 4040, 'n_tokens_neox': 3827, 'n_words': 857}