// Copyright 2018 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "core/device.h"
#include "tasking.h"

OIDN_NAMESPACE_BEGIN

  class CPUEngine;

  // CPU instruction set
  enum class CPUArch
  {
    Unknown,
    SSE2,
    SSE4,
    AVX2,
    AVX512,
    AVX512_AMXFP16,
    NEON
  };

  class CPUPhysicalDevice final : public PhysicalDevice
  {
  public:
    CPUArch arch = CPUArch::Unknown;

    explicit CPUPhysicalDevice(int score);
  };

  class CPUDevice final : public Device
  {
    friend class CPUEngine;

  public:
    static std::vector<Ref<PhysicalDevice>> getPhysicalDevices();
    static std::string getName();
    static CPUArch getNativeArch();

    explicit CPUDevice(const Ref<CPUPhysicalDevice>& physicalDevice);

    DeviceType getType() const override { return DeviceType::CPU; }

    bool needWeightAndBiasOnDevice() const override { return false; } // no need to copy
    Storage getPtrStorage(const void* ptr) override;

    int getInt(const std::string& name) override;
    void setInt(const std::string& name, int value) override;

    void wait() override;

    CPUArch getArch() const { return arch; }

  protected:
    void init() override;

  private:
    CPUArch arch = CPUArch::Unknown;

    int numThreads = 0; // autodetect by default
    bool setAffinity = true;

    // Used only for initialization
    Ref<CPUPhysicalDevice> physicalDevice;
  };

OIDN_NAMESPACE_END
