<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016
// Mehdi Goli    Codeplay Software Ltd.
// Ralph Potter  Codeplay Software Ltd.
// Luke Iwanski  Codeplay Software Ltd.
// Contact: <eigen@codeplay.com>
// Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX
#define EIGEN_TEST_FUNC cxx11_tensor_sycl
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#define EIGEN_USE_SYCL

#include "main.h"
#include <unsupported/Eigen/CXX11/Tensor>

using Eigen::array;
using Eigen::SyclDevice;
using Eigen::Tensor;
using Eigen::TensorMap;

void test_sycl_cpu(const Eigen::SyclDevice &sycl_device) {

  int sizeDim1 = 100;
  int sizeDim2 = 100;
  int sizeDim3 = 100;
  array<int, 3> tensorRange = {{sizeDim1, sizeDim2, sizeDim3}};
  Tensor<float, 3> in1(tensorRange);
  Tensor<float, 3> in2(tensorRange);
  Tensor<float, 3> in3(tensorRange);
  Tensor<float, 3> out(tensorRange);

  in2 = in2.random();
  in3 = in3.random();

  float * gpu_in1_data  = static_cast<float*>(sycl_device.allocate(in1.dimensions().TotalSize()*sizeof(float)));
  float * gpu_in2_data  = static_cast<float*>(sycl_device.allocate(in2.dimensions().TotalSize()*sizeof(float)));
  float * gpu_in3_data  = static_cast<float*>(sycl_device.allocate(in3.dimensions().TotalSize()*sizeof(float)));
  float * gpu_out_data =  static_cast<float*>(sycl_device.allocate(out.dimensions().TotalSize()*sizeof(float)));

  TensorMap<Tensor<float, 3>> gpu_in1(gpu_in1_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_in2(gpu_in2_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_in3(gpu_in3_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_out(gpu_out_data, tensorRange);

  /// a=1.2f
  gpu_in1.device(sycl_device) = gpu_in1.constant(1.2f);
  sycl_device.memcpyDeviceToHost(in1.data(), gpu_in1_data ,(in1.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(in1(i,j,k), 1.2f);
      }
    }
  }
  printf("a=1.2f Test passed\n");

  /// a=b*1.2f
  gpu_out.device(sycl_device) = gpu_in1 * 1.2f;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data ,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) * 1.2f);
      }
    }
  }
  printf("a=b*1.2f Test Passed\n");

  /// c=a*b
  sycl_device.memcpyHostToDevice(gpu_in2_data, in2.data(),(in2.dimensions().TotalSize())*sizeof(float));
  gpu_out.device(sycl_device) = gpu_in1 * gpu_in2;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) *
                             in2(i,j,k));
      }
    }
  }
  printf("c=a*b Test Passed\n");

  /// c=a+b
  gpu_out.device(sycl_device) = gpu_in1 + gpu_in2;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) +
                             in2(i,j,k));
      }
    }
  }
  printf("c=a+b Test Passed\n");

  /// c=a*a
  gpu_out.device(sycl_device) = gpu_in1 * gpu_in1;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) *
                             in1(i,j,k));
      }
    }
  }
  printf("c= a*a Test Passed\n");

  //a*3.14f + b*2.7f
  gpu_out.device(sycl_device) =  gpu_in1 * gpu_in1.constant(3.14f) + gpu_in2 * gpu_in2.constant(2.7f);
  sycl_device.memcpyDeviceToHost(out.data(),gpu_out_data,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) * 3.14f
                       + in2(i,j,k) * 2.7f);
      }
    }
  }
  printf("a*3.14f + b*2.7f Test Passed\n");

  ///d= (a>0.5? b:c)
  sycl_device.memcpyHostToDevice(gpu_in3_data, in3.data(),(in3.dimensions().TotalSize())*sizeof(float));
  gpu_out.device(sycl_device) =(gpu_in1 > gpu_in1.constant(0.5f)).select(gpu_in2, gpu_in3);
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.dimensions().TotalSize())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i, j, k), (in1(i, j, k) > 0.5f)
                                                ? in2(i, j, k)
                                                : in3(i, j, k));
      }
    }
  }
  printf("d= (a>0.5? b:c) Test Passed\n");
  sycl_device.deallocate(gpu_in1_data);
  sycl_device.deallocate(gpu_in2_data);
  sycl_device.deallocate(gpu_in3_data);
  sycl_device.deallocate(gpu_out_data);
}
void test_cxx11_tensor_sycl() {
  cl::sycl::gpu_selector s;
  Eigen::SyclDevice sycl_device(s);
  CALL_SUBTEST(test_sycl_cpu(sycl_device));
}
<commit_msg>Added a test to validate memory transfers between host and sycl device<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016
// Mehdi Goli    Codeplay Software Ltd.
// Ralph Potter  Codeplay Software Ltd.
// Luke Iwanski  Codeplay Software Ltd.
// Contact: <eigen@codeplay.com>
// Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX
#define EIGEN_TEST_FUNC cxx11_tensor_sycl
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#define EIGEN_USE_SYCL

#include "main.h"
#include <unsupported/Eigen/CXX11/Tensor>

using Eigen::array;
using Eigen::SyclDevice;
using Eigen::Tensor;
using Eigen::TensorMap;

void test_sycl_mem_transfers(const Eigen::SyclDevice &sycl_device) {
  int sizeDim1 = 100;
  int sizeDim2 = 100;
  int sizeDim3 = 100;
  array<int, 3> tensorRange = {{sizeDim1, sizeDim2, sizeDim3}};
  Tensor<float, 3> in1(tensorRange);
  Tensor<float, 3> out1(tensorRange);
  Tensor<float, 3> out2(tensorRange);
  Tensor<float, 3> out3(tensorRange);

  in1 = in1.random();

  float* gpu_data1  = static_cast<float*>(sycl_device.allocate(in1.size()*sizeof(float)));
  float* gpu_data2  = static_cast<float*>(sycl_device.allocate(out1.size()*sizeof(float)));
  //float* gpu_data =  static_cast<float*>(sycl_device.allocate(out2.size()*sizeof(float)));

  TensorMap<Tensor<float, 3>> gpu1(gpu_data1, tensorRange);
  TensorMap<Tensor<float, 3>> gpu2(gpu_data2, tensorRange);
  //TensorMap<Tensor<float, 3>> gpu_out2(gpu_out2_data, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data1, in1.data(),(in1.size())*sizeof(float));
  sycl_device.memcpyHostToDevice(gpu_data2, in1.data(),(in1.size())*sizeof(float));
  gpu1.device(sycl_device) = gpu1 * 3.14f;
  gpu2.device(sycl_device) = gpu2 * 2.7f;
  sycl_device.memcpyDeviceToHost(out1.data(), gpu_data1,(out1.size())*sizeof(float));
  sycl_device.memcpyDeviceToHost(out2.data(), gpu_data1,(out2.size())*sizeof(float));
  sycl_device.memcpyDeviceToHost(out3.data(), gpu_data2,(out3.size())*sizeof(float));
  //  sycl_device.Synchronize();

  for (int i = 0; i < in1.size(); ++i) {
    VERIFY_IS_APPROX(out1(i), in1(i) * 3.14f);
    VERIFY_IS_APPROX(out2(i), in1(i) * 3.14f);
    VERIFY_IS_APPROX(out3(i), in1(i) * 2.7f);
  }

  sycl_device.deallocate(gpu_data1);
  sycl_device.deallocate(gpu_data2);
}

void test_sycl_computations(const Eigen::SyclDevice &sycl_device) {

  int sizeDim1 = 100;
  int sizeDim2 = 100;
  int sizeDim3 = 100;
  array<int, 3> tensorRange = {{sizeDim1, sizeDim2, sizeDim3}};
  Tensor<float, 3> in1(tensorRange);
  Tensor<float, 3> in2(tensorRange);
  Tensor<float, 3> in3(tensorRange);
  Tensor<float, 3> out(tensorRange);

  in2 = in2.random();
  in3 = in3.random();

  float * gpu_in1_data  = static_cast<float*>(sycl_device.allocate(in1.size()*sizeof(float)));
  float * gpu_in2_data  = static_cast<float*>(sycl_device.allocate(in2.size()*sizeof(float)));
  float * gpu_in3_data  = static_cast<float*>(sycl_device.allocate(in3.size()*sizeof(float)));
  float * gpu_out_data =  static_cast<float*>(sycl_device.allocate(out.size()*sizeof(float)));

  TensorMap<Tensor<float, 3>> gpu_in1(gpu_in1_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_in2(gpu_in2_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_in3(gpu_in3_data, tensorRange);
  TensorMap<Tensor<float, 3>> gpu_out(gpu_out_data, tensorRange);

  /// a=1.2f
  gpu_in1.device(sycl_device) = gpu_in1.constant(1.2f);
  sycl_device.memcpyDeviceToHost(in1.data(), gpu_in1_data ,(in1.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(in1(i,j,k), 1.2f);
      }
    }
  }
  printf("a=1.2f Test passed\n");

  /// a=b*1.2f
  gpu_out.device(sycl_device) = gpu_in1 * 1.2f;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data ,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) * 1.2f);
      }
    }
  }
  printf("a=b*1.2f Test Passed\n");

  /// c=a*b
  sycl_device.memcpyHostToDevice(gpu_in2_data, in2.data(),(in2.size())*sizeof(float));
  gpu_out.device(sycl_device) = gpu_in1 * gpu_in2;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) *
                             in2(i,j,k));
      }
    }
  }
  printf("c=a*b Test Passed\n");

  /// c=a+b
  gpu_out.device(sycl_device) = gpu_in1 + gpu_in2;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) +
                             in2(i,j,k));
      }
    }
  }
  printf("c=a+b Test Passed\n");

  /// c=a*a
  gpu_out.device(sycl_device) = gpu_in1 * gpu_in1;
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) *
                             in1(i,j,k));
      }
    }
  }
  printf("c= a*a Test Passed\n");

  //a*3.14f + b*2.7f
  gpu_out.device(sycl_device) =  gpu_in1 * gpu_in1.constant(3.14f) + gpu_in2 * gpu_in2.constant(2.7f);
  sycl_device.memcpyDeviceToHost(out.data(),gpu_out_data,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i,j,k),
                         in1(i,j,k) * 3.14f
                       + in2(i,j,k) * 2.7f);
      }
    }
  }
  printf("a*3.14f + b*2.7f Test Passed\n");

  ///d= (a>0.5? b:c)
  sycl_device.memcpyHostToDevice(gpu_in3_data, in3.data(),(in3.size())*sizeof(float));
  gpu_out.device(sycl_device) =(gpu_in1 > gpu_in1.constant(0.5f)).select(gpu_in2, gpu_in3);
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data,(out.size())*sizeof(float));
  for (int i = 0; i < sizeDim1; ++i) {
    for (int j = 0; j < sizeDim2; ++j) {
      for (int k = 0; k < sizeDim3; ++k) {
        VERIFY_IS_APPROX(out(i, j, k), (in1(i, j, k) > 0.5f)
                                                ? in2(i, j, k)
                                                : in3(i, j, k));
      }
    }
  }
  printf("d= (a>0.5? b:c) Test Passed\n");
  sycl_device.deallocate(gpu_in1_data);
  sycl_device.deallocate(gpu_in2_data);
  sycl_device.deallocate(gpu_in3_data);
  sycl_device.deallocate(gpu_out_data);
}

void test_cxx11_tensor_sycl() {
  cl::sycl::gpu_selector s;
  Eigen::SyclDevice sycl_device(s);
  CALL_SUBTEST(test_sycl_mem_transfers(sycl_device));
  CALL_SUBTEST(test_sycl_computations(sycl_device));
}
<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://visualizationlibrary.org                                                   */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#include "BaseDemo.hpp"
#include <vlCore/glsl_math.hpp>
#include <vlGraphics/GLSL.hpp>
#include <vlGraphics/Light.hpp>
#include <vlGraphics/Text.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlCore/VisualizationLibrary.hpp>
#include <vlCore/FileSystem.hpp>
#include <vlCore/DiskDirectory.hpp>
#include <vlCore/ResourceDatabase.hpp>
#include <vlCore/LoadWriterManager.hpp>
#include <vlGraphics/TriangleStripGenerator.hpp>
#include <vlGraphics/DoubleVertexRemover.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlGraphics/plugins/ioVLX.hpp>
#include <vlGraphics/DepthSortCallback.hpp>
#include <vlGraphics/GeometryPrimitives.hpp>
#include <vlGraphics/RendererVivid.hpp>

#define MODEL_FILENAME "/vivid/bunny.ply"

vl::ref<vl::RendererVivid> vivid = new vl::RendererVivid();

class App_Vivid: public BaseDemo
{
public:
  //--------------------------------------------------------------------------
  void keyPressEvent(unsigned short unicode_ch, vl::EKey key)
  {
    // BaseDemo::keyReleaseEvent(unicode_ch, key);

    switch((unsigned char)tolower(unicode_ch))
    {
	    case 'q':
        vivid->setUseQueryObject(!vivid->useQueryObject());
		    break;
	    case '+':
        vivid->setNumPasses(vivid->numPasses() + 1);
		    break;
	    case '-':
        if (vivid->numPasses() > 1) {
          vivid->setNumPasses(vivid->numPasses() - 1);
        }
		    break;
	    case '1':
        vivid->setRenderingMode(vl::RendererVivid::DualDepthPeeling);
		    break;
	    case '2':
		    vivid->setRenderingMode(vl::RendererVivid::FrontToBackDepthPeeling);
		    break;
	    case '3':
		    vivid->setRenderingMode(vl::RendererVivid::NoDepthPeeling);
		    break;
	    /*case 'a':
		    g_opacity -= 0.05;
        g_opacity = vl::max(g_opacity, 0.0f);
		    break;
	    case 'd':
		    g_opacity += 0.05;
		    g_opacity = vl::min(g_opacity, 1.0f);
		    break;
	    case 'b':
		    g_backgroundColor = (g_backgroundColor == g_white) ? g_black : g_white;
		    break;*/
    }

    const char* method[] = { "NoDepthPeeling", "DualDepthPeeling", "FrontToBackDepthPeeling" };
    printf("method:           %s\n", method[vivid->renderingMode()]);
    printf("pass counter:     %d\n", vivid->passCounter());
    printf("num passes:       %d\n", vivid->numPasses());
    printf("use query object: %d\n", vivid->useQueryObject());
    openglContext()->update();
  }

  void initEvent()
  {
    vl::Log::print( vl::Say("GL_VERSION: %s\n") << glGetString(GL_VERSION));
    vl::Log::print( vl::Say("GL_RENDERER: %s\n\n") << glGetString(GL_RENDERER));

    vl::Log::notify(appletInfo());
    openglContext()->setContinuousUpdate(false);
    rendering()->as<vl::Rendering>()->setNearFarClippingPlanesOptimized(true);

    // Setup the vivid renderer
    vivid->setFramebuffer(openglContext()->framebuffer());
    rendering()->as<vl::Rendering>()->setRenderer( vivid.get() );

    // initScene();
    std::vector<vl::String> files;
    files.push_back(MODEL_FILENAME);
    loadModel(files);
  }

  void initScene() {
    vl::ref<vl::Effect> fx1 = new vl::Effect;
    fx1->shader()->enable(vl::EN_BLEND);
    fx1->shader()->enable(vl::EN_DEPTH_TEST);
    fx1->shader()->enable(vl::EN_LIGHTING);
    fx1->shader()->setRenderState( new vl::Light, 0 );
    fx1->shader()->gocLightModel()->setTwoSide(true);
    fx1->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 1.0f, 1.0f, 1.0f) );
    fx1->shader()->gocMaterial()->setTransparency( 0.5f );

    vl::ref<vl::Effect> fx2 = new vl::Effect;
    fx2->shader()->disable(vl::EN_BLEND);
    fx2->shader()->enable(vl::EN_DEPTH_TEST);
    fx2->shader()->enable(vl::EN_LIGHTING);
    fx2->shader()->setRenderState( new vl::Light, 0 );
    fx2->shader()->gocLightModel()->setTwoSide(true);
    fx2->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 0.0f, 0.0f, 1.0f) );
    fx2->shader()->gocMaterial()->setTransparency( 1.0f );

    vl::ref< vl::Transform > tr1 = new vl::Transform();
    tr1->setLocalAndWorldMatrix(vl::mat4::getTranslation(+0.025f, 0, 0));

    vl::ref< vl::Transform > tr2 = new vl::Transform();
    tr2->setLocalAndWorldMatrix(vl::mat4::getTranslation(-0.025f, 0, 0) * vl::mat4::getRotationXYZ(90, 0, 0));

    vl::ref< vl::Geometry > torus = vl::makeTorus( vl::vec3( 0, 0, 0 ), 0.1f, 0.02f, 20, 40 );

    sceneManager()->tree()->addActor( torus.get(), fx1.get(), tr1.get() );
    sceneManager()->tree()->addActor( torus.get(), fx2.get(), tr2.get() );

    adjustScene();
  }

  void adjustScene() {
    // position the camera to nicely see the objects in the scene
    trackball()->adjustView( rendering()->as<vl::Rendering>(), vl::vec3(0,0,1), vl::vec3(0,1,0), 1.0f );

    // throttle ghost camera manipulator speed based on the scene size, using a simple euristic formula
    sceneManager()->computeBounds();
    const vl::AABB& scene_aabb = sceneManager()->boundingBox();
    vl::real speed = (scene_aabb.width() + scene_aabb.height() + scene_aabb.depth()) / 20.0f;
    ghostCameraManipulator()->setMovementSpeed(speed);
  }

  void loadModel(const std::vector<vl::String>& files)
  {
    // default effects

    sceneManager()->tree()->actors()->clear();

    for(unsigned int i=0; i<files.size(); ++i)
    {
      vl::ref<vl::ResourceDatabase> resource_db = vl::loadResource(files[i], false);

      if (!resource_db || resource_db->count<vl::Actor>() == 0)
      {
        VL_LOG_ERROR << "No data found.\n";
        continue;
      }

#if 0
      // VLX save
      String save_path = files[i].extractPath() + files[i].extractFileName() + ".vlb";
      saveVLB(save_path, resource_db.get());
#endif

      showStatistics(resource_db);

      for(size_t i=0; i<resource_db->resources().size(); ++i)
      {
        vl::Actor* act = resource_db->resources()[i]->as<vl::Actor>();

        if (!act)
          continue;

        // act->actorEventCallbacks()->push_back( new vl::DepthSortCallback );

        vl::ref<vl::Effect> fx1 = new vl::Effect;
        fx1->shader()->enable(vl::EN_BLEND);
        fx1->shader()->enable(vl::EN_DEPTH_TEST);
        fx1->shader()->enable(vl::EN_LIGHTING);
        fx1->shader()->disable(vl::EN_CULL_FACE);
        fx1->shader()->setRenderState( new vl::Light, 0 );
        fx1->shader()->gocLightModel()->setTwoSide(true);
        fx1->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 0.0f, 0.0f, 1.0f) );
        fx1->shader()->gocMaterial()->setTransparency( 0.5f );

        act->setEffect(fx1.get());

        vl::Geometry* geom = act->lod(0)->as<vl::Geometry>();
        geom->computeNormals();

        sceneManager()->tree()->addActor(act);
      }
    }

    adjustScene();
  }

  void showStatistics(vl::ref<vl::ResourceDatabase> res_db)
  {
    std::set<vl::Geometry*> geometries;
    std::vector< vl::ref<vl::Geometry> > geom_db;
    std::vector< vl::ref<vl::Actor> > actor_db;

    res_db->get<vl::Actor>(actor_db);
    res_db->get<vl::Geometry>(geom_db);

    // find number of unique geometries

    for(size_t i=0; i<geom_db.size(); ++i)
      geometries.insert( geom_db[i].get() );

    for(size_t i=0; i<actor_db.size(); ++i)
    {
      vl::Geometry* geom = actor_db[i]->lod(0)->as<vl::Geometry>();
      if (geom)
        geometries.insert( geom );
    }

    int total_triangles = 0;
    int total_draw_calls = 0;
    for( std::set<vl::Geometry*>::iterator it = geometries.begin(); it != geometries.end(); ++it )
    {
      total_draw_calls += (*it)->drawCalls().size();
      for(int i=0; i < (*it)->drawCalls().size(); ++i )
        total_triangles += (*it)->drawCalls().at(i)->countTriangles();
    }

    VL_LOG_PRINT << "Statistics:\n";
    VL_LOG_PRINT << "+ Total triangles  = " << total_triangles << "\n";
    VL_LOG_PRINT << "+ Total draw calls = " << total_draw_calls << "\n";
    VL_LOG_PRINT << "+ Actors           = " << actor_db.size() << "\n";
    VL_LOG_PRINT << "+ Geometries       = " << geometries.size() << "\n";
  }

  void fileDroppedEvent(const std::vector<vl::String>& files)
  {
    loadModel(files);
    // update the rendering
    openglContext()->update();
  }

protected:
  std::set< vl::ref<vl::Effect> > mEffects;
  std::vector<vl::String> mLastShaders;
};

// Have fun!

BaseDemo* Create_App_Vivid() { return new App_Vivid; }
<commit_msg>Vivid app updated<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://visualizationlibrary.org                                                   */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#include "BaseDemo.hpp"
#include <vlCore/glsl_math.hpp>
#include <vlGraphics/GLSL.hpp>
#include <vlGraphics/Light.hpp>
#include <vlGraphics/Text.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlCore/VisualizationLibrary.hpp>
#include <vlCore/FileSystem.hpp>
#include <vlCore/DiskDirectory.hpp>
#include <vlCore/ResourceDatabase.hpp>
#include <vlCore/LoadWriterManager.hpp>
#include <vlGraphics/TriangleStripGenerator.hpp>
#include <vlGraphics/DoubleVertexRemover.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlGraphics/plugins/ioVLX.hpp>
#include <vlGraphics/DepthSortCallback.hpp>
#include <vlGraphics/GeometryPrimitives.hpp>
#include <vlGraphics/RendererVivid.hpp>

#define MODEL_FILENAME "/vivid/bunny.ply"

vl::ref<vl::RendererVivid> vivid = new vl::RendererVivid();

class App_Vivid: public BaseDemo
{
public:
  //--------------------------------------------------------------------------
  void keyPressEvent(unsigned short unicode_ch, vl::EKey key)
  {
    // BaseDemo::keyReleaseEvent(unicode_ch, key);

    switch((unsigned char)tolower(unicode_ch))
    {
	    case 'r':
        vivid->initShaders();
		    break;
	    case 'q':
        vivid->setUseQueryObject(!vivid->useQueryObject());
		    break;
	    case '+':
        vivid->setNumPasses(vivid->numPasses() + 1);
		    break;
	    case '-':
        if (vivid->numPasses() > 1) {
          vivid->setNumPasses(vivid->numPasses() - 1);
        }
		    break;
	    case '1':
        vivid->setRenderingMode(vl::RendererVivid::DualDepthPeeling);
		    break;
	    case '2':
		    vivid->setRenderingMode(vl::RendererVivid::FrontToBackDepthPeeling);
		    break;
	    case '3':
		    vivid->setRenderingMode(vl::RendererVivid::NoDepthPeeling);
		    break;
	    /*case 'a':
		    g_opacity -= 0.05;
        g_opacity = vl::max(g_opacity, 0.0f);
		    break;
	    case 'd':
		    g_opacity += 0.05;
		    g_opacity = vl::min(g_opacity, 1.0f);
		    break;
	    case 'b':
		    g_backgroundColor = (g_backgroundColor == g_white) ? g_black : g_white;
		    break;*/
    }

    const char* method[] = { "NoDepthPeeling", "DualDepthPeeling", "FrontToBackDepthPeeling" };
    printf("method:           %s\n", method[vivid->renderingMode()]);
    printf("pass counter:     %d\n", vivid->passCounter());
    printf("num passes:       %d\n", vivid->numPasses());
    printf("use query object: %d\n", vivid->useQueryObject());
    printf("---\n");
    openglContext()->update();
  }

  void initEvent()
  {
    vl::Log::print( vl::Say("GL_VERSION: %s\n") << glGetString(GL_VERSION));
    vl::Log::print( vl::Say("GL_RENDERER: %s\n\n") << glGetString(GL_RENDERER));

    vl::Log::notify(appletInfo());
    openglContext()->setContinuousUpdate(false);
    rendering()->as<vl::Rendering>()->setNearFarClippingPlanesOptimized(true);

    // Setup the vivid renderer
    vivid->setFramebuffer(openglContext()->framebuffer());
    rendering()->as<vl::Rendering>()->setRenderer( vivid.get() );

    // initScene();
    std::vector<vl::String> files;
    files.push_back(MODEL_FILENAME);
    loadModel(files);
  }

  void initScene() {
    vl::ref<vl::Effect> fx1 = new vl::Effect;
    fx1->shader()->enable(vl::EN_BLEND);
    fx1->shader()->enable(vl::EN_DEPTH_TEST);
    fx1->shader()->enable(vl::EN_LIGHTING);
    fx1->shader()->setRenderState( new vl::Light, 0 );
    fx1->shader()->gocLightModel()->setTwoSide(true);
    fx1->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 1.0f, 1.0f, 0.5f) );

    vl::ref<vl::Effect> fx2 = new vl::Effect;
    fx2->shader()->disable(vl::EN_BLEND);
    fx2->shader()->enable(vl::EN_DEPTH_TEST);
    fx2->shader()->enable(vl::EN_LIGHTING);
    fx2->shader()->setRenderState( new vl::Light, 0 );
    fx2->shader()->gocLightModel()->setTwoSide(true);
    fx2->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 0.0f, 0.0f, 1.0f) );

    vl::ref< vl::Transform > tr1 = new vl::Transform();
    tr1->setLocalAndWorldMatrix(vl::mat4::getTranslation(+0.025f, 0, 0));

    vl::ref< vl::Transform > tr2 = new vl::Transform();
    tr2->setLocalAndWorldMatrix(vl::mat4::getTranslation(-0.025f, 0, 0) * vl::mat4::getRotationXYZ(90, 0, 0));

    vl::ref< vl::Geometry > torus = vl::makeTorus( vl::vec3( 0, 0, 0 ), 0.1f, 0.02f, 20, 40 );

    sceneManager()->tree()->addActor( torus.get(), fx1.get(), tr1.get() );
    sceneManager()->tree()->addActor( torus.get(), fx2.get(), tr2.get() );

    adjustScene();
  }

  void adjustScene() {
    // position the camera to nicely see the objects in the scene
    trackball()->adjustView( rendering()->as<vl::Rendering>(), vl::vec3(0,0,1), vl::vec3(0,1,0), 1.0f );

    // throttle ghost camera manipulator speed based on the scene size, using a simple euristic formula
    sceneManager()->computeBounds();
    const vl::AABB& scene_aabb = sceneManager()->boundingBox();
    vl::real speed = (scene_aabb.width() + scene_aabb.height() + scene_aabb.depth()) / 20.0f;
    ghostCameraManipulator()->setMovementSpeed(speed);
  }

  void loadModel(const std::vector<vl::String>& files)
  {
    // default effects

    sceneManager()->tree()->actors()->clear();

    for(unsigned int i=0; i<files.size(); ++i)
    {
      vl::ref<vl::ResourceDatabase> resource_db = vl::loadResource(files[i], false);

      if (!resource_db || resource_db->count<vl::Actor>() == 0)
      {
        VL_LOG_ERROR << "No data found.\n";
        continue;
      }

#if 0
      // VLX save
      String save_path = files[i].extractPath() + files[i].extractFileName() + ".vlb";
      saveVLB(save_path, resource_db.get());
#endif

      showStatistics(resource_db);

      for(size_t i=0; i<resource_db->resources().size(); ++i)
      {
        vl::Actor* act = resource_db->resources()[i]->as<vl::Actor>();

        if (!act)
          continue;

        // act->actorEventCallbacks()->push_back( new vl::DepthSortCallback );

        vl::ref<vl::Effect> fx1 = new vl::Effect;
        fx1->shader()->enable(vl::EN_BLEND);
        fx1->shader()->enable(vl::EN_DEPTH_TEST);
        fx1->shader()->enable(vl::EN_LIGHTING);
        fx1->shader()->disable(vl::EN_CULL_FACE);
        fx1->shader()->setRenderState( new vl::Light, 0 );
        fx1->shader()->gocLightModel()->setTwoSide(true);
        fx1->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f, 0.0f, 0.0f, 1.0f) );

        act->setEffect(fx1.get());

        vl::Geometry* geom = act->lod(0)->as<vl::Geometry>();
        geom->computeNormals();

        sceneManager()->tree()->addActor(act);
      }
    }

    adjustScene();
  }

  void showStatistics(vl::ref<vl::ResourceDatabase> res_db)
  {
    std::set<vl::Geometry*> geometries;
    std::vector< vl::ref<vl::Geometry> > geom_db;
    std::vector< vl::ref<vl::Actor> > actor_db;

    res_db->get<vl::Actor>(actor_db);
    res_db->get<vl::Geometry>(geom_db);

    // find number of unique geometries

    for(size_t i=0; i<geom_db.size(); ++i)
      geometries.insert( geom_db[i].get() );

    for(size_t i=0; i<actor_db.size(); ++i)
    {
      vl::Geometry* geom = actor_db[i]->lod(0)->as<vl::Geometry>();
      if (geom)
        geometries.insert( geom );
    }

    int total_triangles = 0;
    int total_draw_calls = 0;
    for( std::set<vl::Geometry*>::iterator it = geometries.begin(); it != geometries.end(); ++it )
    {
      total_draw_calls += (*it)->drawCalls().size();
      for(int i=0; i < (*it)->drawCalls().size(); ++i )
        total_triangles += (*it)->drawCalls().at(i)->countTriangles();
    }

    VL_LOG_PRINT << "Statistics:\n";
    VL_LOG_PRINT << "+ Total triangles  = " << total_triangles << "\n";
    VL_LOG_PRINT << "+ Total draw calls = " << total_draw_calls << "\n";
    VL_LOG_PRINT << "+ Actors           = " << actor_db.size() << "\n";
    VL_LOG_PRINT << "+ Geometries       = " << geometries.size() << "\n";
  }

  void fileDroppedEvent(const std::vector<vl::String>& files)
  {
    loadModel(files);
    // update the rendering
    openglContext()->update();
  }

protected:
  std::set< vl::ref<vl::Effect> > mEffects;
  std::vector<vl::String> mLastShaders;
};

// Have fun!

BaseDemo* Create_App_Vivid() { return new App_Vivid; }
<|endoftext|>


<commit_before>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
                           Deniz Erbilgin 2017
*/

/*
 * OTRadValve tests of secure frame operations dependent on OTASEGCM
 * with a particular view to managing stack depth to avoid overflow
 * especially on very limited RAM platforms such as AVR.
 */

// Only enable these tests if the OTAESGCM library is marked as available.
#if defined(EXT_AVAILABLE_ARDUINO_LIB_OTAESGCM)

#include <gtest/gtest.h>
#include <stdio.h>
#include <stdlib.h>

#include <OTAESGCM.h>
#include <OTRadioLink.h>

static const int AES_KEY_SIZE = 128; // in bits
static const int GCM_NONCE_LENGTH = 12; // in bytes
static const int GCM_TAG_LENGTH = 16; // in bytes (default 16, 12 possible)

// All-zeros const 16-byte/128-bit key.
// Can be used for other purposes.
static const uint8_t zeroBlock[16] = { };

// Max stack usage in bytes
// 20170511
//           enc, dec, enc*, dec*
// - DE:     208, 208, 208,  208
// - DHD:    ???, ???, 358,  ???
// - Travis: 192, 224, ???,  ???
// * using a workspace
#ifndef __APPLE__
static constexpr unsigned int maxStackSecureFrameEncode = 328;
static constexpr unsigned int maxStackSecureFrameDecode = 328;
#else
// On DHD's system, secure frame enc/decode uses 358 bytes (20170511)
static constexpr unsigned int maxStackSecureFrameEncode = 416;
static constexpr unsigned int maxStackSecureFrameDecode = 416;
#endif // __APPLE__

TEST(SimpleSecureFrame, StackCheckerWorks)
{
    // Set up stack usage checks
    OTV0P2BASE::RAMEND = OTV0P2BASE::getSP();
    OTV0P2BASE::MemoryChecks::resetMinSP();
    OTV0P2BASE::MemoryChecks::recordIfMinSP();
    const size_t baseStack = OTV0P2BASE::MemoryChecks::getMinSP();
    // Uncomment to print stack usage
    EXPECT_NE((size_t)0, baseStack);
}

#endif // ARDUINO_LIB_OTAESGCM
<commit_msg>TODO-1114: new test set<commit_after>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
                           Deniz Erbilgin 2017
*/

/*
 * OTRadValve tests of secure frame operations dependent on OTASEGCM
 * with a particular view to managing stack depth to avoid overflow
 * especially on very limited RAM platforms such as AVR.
 */

// Only enable these tests if the OTAESGCM library is marked as available.
#if defined(EXT_AVAILABLE_ARDUINO_LIB_OTAESGCM)

#include <gtest/gtest.h>
#include <stdio.h>
#include <stdlib.h>

#include <OTAESGCM.h>
#include <OTRadioLink.h>

static const int AES_KEY_SIZE = 128; // in bits
static const int GCM_NONCE_LENGTH = 12; // in bytes
static const int GCM_TAG_LENGTH = 16; // in bytes (default 16, 12 possible)

// All-zeros const 16-byte/128-bit key.
// Can be used for other purposes.
static const uint8_t zeroBlock[16] = { };

// Max stack usage in bytes
// 20170511
//           enc, dec, enc*, dec*
// - DE:     208, 208, 208,  208
// - DHD:    ???, ???, 358,  ???
// - Travis: 192, 224, ???,  ???
// * using a workspace
#ifndef __APPLE__
static constexpr unsigned int maxStackSecureFrameEncode = 328;
static constexpr unsigned int maxStackSecureFrameDecode = 328;
#else
// On DHD's system, secure frame enc/decode uses 358 bytes (20170511)
static constexpr unsigned int maxStackSecureFrameEncode = 416;
static constexpr unsigned int maxStackSecureFrameDecode = 416;
#endif // __APPLE__

TEST(SecureOpStackDepth, StackCheckerWorks)
{
    // Set up stack usage checks
    OTV0P2BASE::RAMEND = OTV0P2BASE::getSP();
    OTV0P2BASE::MemoryChecks::resetMinSP();
    OTV0P2BASE::MemoryChecks::recordIfMinSP();
    const size_t baseStack = OTV0P2BASE::MemoryChecks::getMinSP();
    // Uncomment to print stack usage
    EXPECT_NE((size_t)0, baseStack);
}

#endif // ARDUINO_LIB_OTAESGCM
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file arch.inl
 *  \brief Inline file for arch.h.
 */

#include <string>
#include <algorithm>

#include <thrust/detail/util/blocking.h>
#include <thrust/system_error.h>
#include <map>

// #include this for make_uint3
#include <vector_functions.h>

namespace thrust
{
namespace experimental
{
namespace arch
{
namespace detail
{

inline void checked_get_current_device_properties(cudaDeviceProp &props)
{
  int current_device = -1;

  cudaError_t error = cudaGetDevice(&current_device);

  if(error)
  {
    throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
  }

  if(current_device < 0)
    throw thrust::experimental::system_error(thrust::experimental::cuda_errc::no_device, thrust::experimental::cuda_category());

  error = cudaGetDeviceProperties(&props, current_device);

  if(error)
  {
    throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
  }
} // end checked_get_current_device_properties()

template <typename KernelFunction>
void checked_get_function_attributes(cudaFuncAttributes& attributes, KernelFunction kernel)
{
  // cache the result of the introspection call because it is expensive
  static std::map<KernelFunction,cudaFuncAttributes> attributes_map;

  // search the cache for the attributes
  typename std::map<KernelFunction,cudaFuncAttributes>::const_iterator iter = attributes_map.find(kernel);

  if(iter == attributes_map.end())
  {
    // the attributes weren't found, ask the runtime to generate them
    cudaError_t error = cudaFuncGetAttributes(&attributes, kernel);

    if(error)
    {
      throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
    }

    // insert the new entry
    attributes_map[kernel] = attributes;
  } // end if
  else
  {
    // use the cached value
    attributes = iter->second;
  } // end else
} // end checked_get_function_attributes()

} // end detail

size_t num_multiprocessors(const cudaDeviceProp& properties)
{
    return properties.multiProcessorCount;
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(const cudaDeviceProp& properties)
{
    // index this array by [major, minor] revision
    // \see NVIDIA_CUDA_Programming_Guide_3.0.pdf p 140
    static const size_t max_active_threads_by_compute_capability[3][4] = \
        {{     0,    0,    0,    0},
         {   768,  768, 1024, 1024},
         {  1536, 1536, 1536, 1536}};

    // produce valid results for new, unknown devices
    if (properties.major > 2 || properties.minor > 3)
        return max_active_threads_by_compute_capability[2][3];
    else
        return max_active_threads_by_compute_capability[properties.major][properties.minor];
} // end max_active_threads_per_multiprocessor()

size_t max_active_threads(const cudaDeviceProp& properties)
{
    return num_multiprocessors(properties) * max_active_threads_per_multiprocessor(properties);
} // end max_active_threads()

dim3 max_grid_dimensions(const cudaDeviceProp& properties)
{
    return make_uint3(properties.maxGridSize[0], properties.maxGridSize[1], properties.maxGridSize[2]);
} // end max_grid_dimensions()

size_t max_active_blocks_per_multiprocessor(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t CTA_SIZE,
                                            size_t dynamic_smem_bytes)
{
    // Determine the maximum number of CTAs that can be run simultaneously per SM
    // This is equivalent to the calculation done in the CUDA Occupancy Calculator spreadsheet
    const size_t regAllocationUnit = (properties.major < 2 && properties.minor < 2) ? 256 : 512; // in registers
    const size_t warpAllocationMultiple = 2;
    const size_t smemAllocationUnit = 512;                                                 // in bytes
    const size_t maxThreadsPerSM = max_active_threads_per_multiprocessor(properties);      // 768, 1024, etc.
    const size_t maxBlocksPerSM = 8;

    // Number of warps (round up to nearest whole multiple of warp size & warp allocation multiple)
    const size_t numWarps = thrust::detail::util::round_i(thrust::detail::util::divide_ri(CTA_SIZE, properties.warpSize), warpAllocationMultiple);

    // Number of regs is regs per thread times number of warps times warp size
    const size_t regsPerCTA = thrust::detail::util::round_i(attributes.numRegs * properties.warpSize * numWarps, regAllocationUnit);

    const size_t smemBytes  = attributes.sharedSizeBytes + dynamic_smem_bytes;
    const size_t smemPerCTA = thrust::detail::util::round_i(smemBytes, smemAllocationUnit);

    const size_t ctaLimitRegs    = regsPerCTA > 0 ? properties.regsPerBlock / regsPerCTA : maxBlocksPerSM;
    const size_t ctaLimitSMem    = smemPerCTA > 0 ? properties.sharedMemPerBlock   / smemPerCTA : maxBlocksPerSM;
    const size_t ctaLimitThreads =                  maxThreadsPerSM                / CTA_SIZE;

    return std::min<size_t>(ctaLimitRegs, std::min<size_t>(ctaLimitSMem, std::min<size_t>(ctaLimitThreads, maxBlocksPerSM)));
}

// Functions that query the runtime for device properties

size_t num_multiprocessors(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return num_multiprocessors(properties);
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads_per_multiprocessor(properties);
}

size_t max_active_threads(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads(properties);
}

dim3 max_grid_dimensions(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_grid_dimensions(properties);
}

template <typename KernelFunction>
size_t max_active_blocks(KernelFunction kernel, const size_t CTA_SIZE, const size_t dynamic_smem_bytes)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return num_multiprocessors(properties) * max_active_blocks_per_multiprocessor(properties, attributes, CTA_SIZE, dynamic_smem_bytes);
}

size_t max_blocksize_with_highest_occupancy(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t dynamic_smem_bytes_per_thread)
{
    size_t max_occupancy = max_active_threads_per_multiprocessor(properties);

    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);

    size_t granularity        = properties.warpSize;

    size_t max_blocksize     = 0;
    size_t highest_occupancy = 0;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        size_t occupancy = blocksize * max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize);

        if (occupancy > highest_occupancy)
        {
            max_blocksize = blocksize;
            highest_occupancy = occupancy;
        }

        // early out, can't do better
        if (highest_occupancy == max_occupancy)
            return max_blocksize;
    }

    return max_blocksize;
}

template <typename KernelFunction>
size_t max_blocksize_with_highest_occupancy(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize_with_highest_occupancy(properties, attributes, dynamic_smem_bytes_per_thread);
}

// TODO unify this with max_blocksize_with_highest_occupancy
size_t max_blocksize(const cudaDeviceProp& properties,
                     const cudaFuncAttributes& attributes,
                     size_t dynamic_smem_bytes_per_thread)
{
    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);

    // TODO eliminate this constant (i assume this is warp_size)
    size_t granularity        = 32;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        if(0 < max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize))
            return blocksize;
    }

    return 0;
}

template <typename KernelFunction>
size_t max_blocksize(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize(properties, attributes, dynamic_smem_bytes_per_thread);
}

} // end namespace arch
} // end namespace experimental
} // end namespace thrust

<commit_msg>Cache device properties inside checked_get_current_device_properties<commit_after>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file arch.inl
 *  \brief Inline file for arch.h.
 */

#include <string>
#include <algorithm>

#include <thrust/detail/util/blocking.h>
#include <thrust/system_error.h>
#include <map>

// #include this for make_uint3
#include <vector_functions.h>

namespace thrust
{
namespace experimental
{
namespace arch
{
namespace detail
{

inline void checked_get_current_device_properties(cudaDeviceProp &props)
{
  int current_device = -1;

  cudaError_t error = cudaGetDevice(&current_device);

  if(error)
  {
    throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
  }

  if(current_device < 0)
    throw thrust::experimental::system_error(thrust::experimental::cuda_errc::no_device, thrust::experimental::cuda_category());

  // cache the result of the introspection call because it is expensive
  static std::map<int,cudaDeviceProp> properties_map;

  // search the cache for the properties
  typename std::map<int,cudaDeviceProp>::const_iterator iter = properties_map.find(current_device);

  if(iter == properties_map.end())
  {
    // the properties weren't found, ask the runtime to generate them
    error = cudaGetDeviceProperties(&props, current_device);

    if(error)
    {
      throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
    }

    // insert the new entry
    properties_map[current_device] = props;
  } // end if
  else
  {
    // use the cached value
    props = iter->second;
  } // end else
} // end checked_get_current_device_properties()

template <typename KernelFunction>
void checked_get_function_attributes(cudaFuncAttributes& attributes, KernelFunction kernel)
{
  // cache the result of the introspection call because it is expensive
  static std::map<KernelFunction,cudaFuncAttributes> attributes_map;

  // search the cache for the attributes
  typename std::map<KernelFunction,cudaFuncAttributes>::const_iterator iter = attributes_map.find(kernel);

  if(iter == attributes_map.end())
  {
    // the attributes weren't found, ask the runtime to generate them
    cudaError_t error = cudaFuncGetAttributes(&attributes, kernel);

    if(error)
    {
      throw thrust::experimental::system_error(error, thrust::experimental::cuda_category());
    }

    // insert the new entry
    attributes_map[kernel] = attributes;
  } // end if
  else
  {
    // use the cached value
    attributes = iter->second;
  } // end else
} // end checked_get_function_attributes()

} // end detail

size_t num_multiprocessors(const cudaDeviceProp& properties)
{
    return properties.multiProcessorCount;
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(const cudaDeviceProp& properties)
{
    // index this array by [major, minor] revision
    // \see NVIDIA_CUDA_Programming_Guide_3.0.pdf p 140
    static const size_t max_active_threads_by_compute_capability[3][4] = \
        {{     0,    0,    0,    0},
         {   768,  768, 1024, 1024},
         {  1536, 1536, 1536, 1536}};

    // produce valid results for new, unknown devices
    if (properties.major > 2 || properties.minor > 3)
        return max_active_threads_by_compute_capability[2][3];
    else
        return max_active_threads_by_compute_capability[properties.major][properties.minor];
} // end max_active_threads_per_multiprocessor()

size_t max_active_threads(const cudaDeviceProp& properties)
{
    return num_multiprocessors(properties) * max_active_threads_per_multiprocessor(properties);
} // end max_active_threads()

dim3 max_grid_dimensions(const cudaDeviceProp& properties)
{
    return make_uint3(properties.maxGridSize[0], properties.maxGridSize[1], properties.maxGridSize[2]);
} // end max_grid_dimensions()

size_t max_active_blocks_per_multiprocessor(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t CTA_SIZE,
                                            size_t dynamic_smem_bytes)
{
    // Determine the maximum number of CTAs that can be run simultaneously per SM
    // This is equivalent to the calculation done in the CUDA Occupancy Calculator spreadsheet
    const size_t regAllocationUnit = (properties.major < 2 && properties.minor < 2) ? 256 : 512; // in registers
    const size_t warpAllocationMultiple = 2;
    const size_t smemAllocationUnit = 512;                                                 // in bytes
    const size_t maxThreadsPerSM = max_active_threads_per_multiprocessor(properties);      // 768, 1024, etc.
    const size_t maxBlocksPerSM = 8;

    // Number of warps (round up to nearest whole multiple of warp size & warp allocation multiple)
    const size_t numWarps = thrust::detail::util::round_i(thrust::detail::util::divide_ri(CTA_SIZE, properties.warpSize), warpAllocationMultiple);

    // Number of regs is regs per thread times number of warps times warp size
    const size_t regsPerCTA = thrust::detail::util::round_i(attributes.numRegs * properties.warpSize * numWarps, regAllocationUnit);

    const size_t smemBytes  = attributes.sharedSizeBytes + dynamic_smem_bytes;
    const size_t smemPerCTA = thrust::detail::util::round_i(smemBytes, smemAllocationUnit);

    const size_t ctaLimitRegs    = regsPerCTA > 0 ? properties.regsPerBlock / regsPerCTA : maxBlocksPerSM;
    const size_t ctaLimitSMem    = smemPerCTA > 0 ? properties.sharedMemPerBlock   / smemPerCTA : maxBlocksPerSM;
    const size_t ctaLimitThreads =                  maxThreadsPerSM                / CTA_SIZE;

    return std::min<size_t>(ctaLimitRegs, std::min<size_t>(ctaLimitSMem, std::min<size_t>(ctaLimitThreads, maxBlocksPerSM)));
}

// Functions that query the runtime for device properties

size_t num_multiprocessors(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return num_multiprocessors(properties);
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads_per_multiprocessor(properties);
}

size_t max_active_threads(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads(properties);
}

dim3 max_grid_dimensions(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_grid_dimensions(properties);
}

template <typename KernelFunction>
size_t max_active_blocks(KernelFunction kernel, const size_t CTA_SIZE, const size_t dynamic_smem_bytes)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return num_multiprocessors(properties) * max_active_blocks_per_multiprocessor(properties, attributes, CTA_SIZE, dynamic_smem_bytes);
}

size_t max_blocksize_with_highest_occupancy(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t dynamic_smem_bytes_per_thread)
{
    size_t max_occupancy = max_active_threads_per_multiprocessor(properties);

    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);

    size_t granularity        = properties.warpSize;

    size_t max_blocksize     = 0;
    size_t highest_occupancy = 0;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        size_t occupancy = blocksize * max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize);

        if (occupancy > highest_occupancy)
        {
            max_blocksize = blocksize;
            highest_occupancy = occupancy;
        }

        // early out, can't do better
        if (highest_occupancy == max_occupancy)
            return max_blocksize;
    }

    return max_blocksize;
}

template <typename KernelFunction>
size_t max_blocksize_with_highest_occupancy(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize_with_highest_occupancy(properties, attributes, dynamic_smem_bytes_per_thread);
}

// TODO unify this with max_blocksize_with_highest_occupancy
size_t max_blocksize(const cudaDeviceProp& properties,
                     const cudaFuncAttributes& attributes,
                     size_t dynamic_smem_bytes_per_thread)
{
    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);

    // TODO eliminate this constant (i assume this is warp_size)
    size_t granularity        = 32;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        if(0 < max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize))
            return blocksize;
    }

    return 0;
}

template <typename KernelFunction>
size_t max_blocksize(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize(properties, attributes, dynamic_smem_bytes_per_thread);
}

} // end namespace arch
} // end namespace experimental
} // end namespace thrust

<|endoftext|>


<commit_before>#include "addresses.h"

#include "analog_random.h"
#include "eeprom_io.h"

namespace {
const char kName[] = "addrs";

// Pick a MAC address for the Ethernet interface. Since the Arduino
// doesn't have its own MAC address assigned at the factory, we must
// pick one. Read more about the issue here:
//
//     https://serverfault.com/a/40720
//     https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
//
// Quoting:
//
//     Universally administered and locally administered addresses are
//     distinguished by setting the second least significant bit of the
//     most significant byte of the address. If the bit is 0, the address
//     is universally administered. If it is 1, the address is locally
//     administered. In the example address 02-00-00-00-00-01 the most
//     significant byte is 02h. The binary is 00000010 and the second
//     least significant bit is 1. Therefore, it is a locally
//     administered address. The bit is 0 in all OUIs.
//
// So, we ensure the low-nibble of the first byte is one of these 8
// hexidecimal values:
//
//    2  == 0010b
//    3  == 0011b
//    6  == 0110b
//    7  == 0111b
//    a  == 1010b
//    b  == 1011b
//    e  == 1110b
//    f  == 1111b
bool pickMACAddress(byte mac[6]) {
  for (int i = 0; i < 6; ++i) {
    int r = AnalogRandom.randomByte();
    if (r < 0) {
      return false;
    }
    mac[i] = r;
  }
  // Make sure this is in the local administered space.
  mac[0] |= 2;
  // And not a multicast address.
  mac[0] &= ~1;
  return true;
}

}  // namespace

void printMACAddress(byte mac[6]) {
  Serial.print(mac[0], HEX);
  for (int i = 1; i < 6; ++i) {
    Serial.print("-");
    Serial.print(mac[i], HEX);
  }
}

void Addresses::save() {
  saveStructToEEPROM(kName, *this);
}

bool Addresses::load() {
  return readStructFromEEPROM(kName, this);
}

void Addresses::generateAddresses() {
  pickMACAddress(mac);

  // A link-local address is in the range 169.254.1.0 to 169.254.254.255,
  // inclusive. Learn more: https://tools.ietf.org/html/rfc3927
  // Also known as Automatic Private IP Addressing.
  int c;
  do {
    c = AnalogRandom.randomByte();
  } while (!(c >= 1 && c <= 254));
  int d;
  while ((d = AnalogRandom.randomByte()) < 0);
  ip = IPAddress(169, 254, c, d);
}
<commit_msg>Add comment explaining the name used to identify the Addresses struct stored in the EEPROM.<commit_after>#include "addresses.h"

#include "analog_random.h"
#include "eeprom_io.h"

namespace {
// This is the name used to identify the data stored in the EEPROM.
// Changing the value (e.g. between "addrs" and "Addrs") has the
// effect of invalidating the currently stored values, which can
// be useful if you want to change the space from whicn one or both
// the addresses is allocated.
const char kName[] = "addrs";

// Pick a MAC address for the Ethernet interface. Since the Arduino
// doesn't have its own MAC address assigned at the factory, we must
// pick one. Read more about the issue here:
//
//     https://serverfault.com/a/40720
//     https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
//
// Quoting:
//
//     Universally administered and locally administered addresses are
//     distinguished by setting the second least significant bit of the
//     most significant byte of the address. If the bit is 0, the address
//     is universally administered. If it is 1, the address is locally
//     administered. In the example address 02-00-00-00-00-01 the most
//     significant byte is 02h. The binary is 00000010 and the second
//     least significant bit is 1. Therefore, it is a locally
//     administered address. The bit is 0 in all OUIs.
//
// So, we ensure the low-nibble of the first byte is one of these 8
// hexidecimal values:
//
//    2  == 0010b
//    3  == 0011b
//    6  == 0110b
//    7  == 0111b
//    a  == 1010b
//    b  == 1011b
//    e  == 1110b
//    f  == 1111b
bool pickMACAddress(byte mac[6]) {
  for (int i = 0; i < 6; ++i) {
    int r = AnalogRandom.randomByte();
    if (r < 0) {
      return false;
    }
    mac[i] = r;
  }
  // Make sure this is in the local administered space.
  mac[0] |= 2;
  // And not a multicast address.
  mac[0] &= ~1;
  return true;
}

}  // namespace

void printMACAddress(byte mac[6]) {
  Serial.print(mac[0], HEX);
  for (int i = 1; i < 6; ++i) {
    Serial.print("-");
    Serial.print(mac[i], HEX);
  }
}

void Addresses::save() {
  saveStructToEEPROM(kName, *this);
}

bool Addresses::load() {
  return readStructFromEEPROM(kName, this);
}

void Addresses::generateAddresses() {
  pickMACAddress(mac);

  // A link-local address is in the range 169.254.1.0 to 169.254.254.255,
  // inclusive. Learn more: https://tools.ietf.org/html/rfc3927
  // Also known as Automatic Private IP Addressing.
  int c;
  do {
    c = AnalogRandom.randomByte();
  } while (!(c >= 1 && c <= 254));
  int d;
  while ((d = AnalogRandom.randomByte()) < 0);
  ip = IPAddress(169, 254, c, d);
}
<|endoftext|>


<commit_before>#include <iostream>
#include "APDS9960.h"

using namespace std;

void handleGesture(APDS9960 apds);

int main()
{
	APDS9960 apds = APDS9960();

	// init wiringPi
	wiringPiSetup();

	// Initialize Serial port
	cout << endl;
	cout << "------------------------------------" << endl;
	cout << "  SparkFun APDS-9960 - GestureTest  " << endl;
	cout << "------------------------------------" << endl;

	// Initialize APDS-9960 (configure I2C and initial values)
	if ( (false == apds.init()) || (false == apds.enableGestureSensor(false)) )
	{
		cout << "APDS-9960 init failed!" << endl;
	}

	while(1)
	{
		handleGesture(apds);
	}
	return 0;
}

void handleGesture(APDS9960 apds)
{
	if ( false == apds.isGestureAvailable() )
	{
		return;
	}

	switch ( apds.readGesture() )
	{
		case DIR_UP:
			cout << "UP" << endl;
			break;
		case DIR_DOWN:
			cout << "DOWN" << endl;
			break;
		case DIR_LEFT:
			cout << "LEFT" << endl;
			break;
		case DIR_RIGHT:
			cout << "RIGHT" << endl;
			break;
		case DIR_NEAR:
			cout << "NEAR" << endl;
			break;
		case DIR_FAR:
			cout << "FAR" << endl;
			break;
		default:
			//Print empty line if gesture in not detected
			cout << endl;
	}
}
<commit_msg>gesture.cpp: Update title<commit_after>#include <iostream>
#include "APDS9960.h"

using namespace std;

void handleGesture(APDS9960 apds);

int main()
{
	APDS9960 apds = APDS9960();

	// init wiringPi
	wiringPiSetup();

	// Initialize Serial port
	cout << endl;
	cout << "------------------------------------" << endl;
	cout << " APDS-9960 - GestureTest  " << endl;
	cout << "------------------------------------" << endl;

	// Initialize APDS-9960 (configure I2C and initial values)
	if ( (false == apds.init()) || (false == apds.enableGestureSensor(false)) )
	{
		cout << "APDS-9960 init failed!" << endl;
	}

	while(1)
	{
		handleGesture(apds);
	}
	return 0;
}

void handleGesture(APDS9960 apds)
{
	if ( false == apds.isGestureAvailable() )
	{
		return;
	}

	switch ( apds.readGesture() )
	{
		case DIR_UP:
			cout << "UP" << endl;
			break;
		case DIR_DOWN:
			cout << "DOWN" << endl;
			break;
		case DIR_LEFT:
			cout << "LEFT" << endl;
			break;
		case DIR_RIGHT:
			cout << "RIGHT" << endl;
			break;
		case DIR_NEAR:
			cout << "NEAR" << endl;
			break;
		case DIR_FAR:
			cout << "FAR" << endl;
			break;
		default:
			//Print empty line if gesture in not detected
			cout << endl;
	}
}
<|endoftext|>


<commit_before>#include <stingray/toolkit/Factory.h>

#include <stingray/toolkit/any.h>

#include <stingray/app/application_context/AppChannel.h>
#include <stingray/app/application_context/ChannelList.h>
#include <stingray/app/scheduler/ScheduledEvents.h>
#include <stingray/app/tests/AutoFilter.h>
#include <stingray/app/zapper/User.h>
#include <stingray/ca/BasicSubscription.h>
#include <stingray/hdmi/IHDMI.h>
#include <stingray/media/ImageFileMediaData.h>
#include <stingray/media/MediaInfoBase.h>
#include <stingray/media/Mp3MediaInfo.h>
#include <stingray/media/formats/flv/MediaInfo.h>
#include <stingray/media/formats/mp4/MediaInfo.h>
#include <stingray/mpeg/Stream.h>
#include <stingray/net/DHCPInterfaceConfiguration.h>
#include <stingray/net/IgnoredInterfaceConfiguration.h>
#include <stingray/net/LinkLocalInterfaceConfiguration.h>
#include <stingray/net/ManualInterfaceConfiguration.h>
#include <stingray/parentalcontrol/AgeRating.h>
#ifdef PLATFORM_EMU
#	include <stingray/platform/emu/scanner/Channel.h>
#endif
#include <stingray/records/FileSystemRecord.h>
#include <stingray/rpc/UrlObjectId.h>
#include <stingray/scanner/DVBServiceId.h>
#include <stingray/scanner/DefaultDVBTBandInfo.h>
#include <stingray/scanner/DefaultMpegService.h>
#include <stingray/scanner/DefaultMpegStreamDescriptor.h>
#include <stingray/scanner/DefaultScanParams.h>
#include <stingray/scanner/DreCasGeographicRegion.h>
#include <stingray/scanner/IServiceId.h>
#include <stingray/scanner/LybidScanParams.h>
#include <stingray/scanner/TricolorGeographicRegion.h>
#include <stingray/scanner/TricolorScanParams.h>
#include <stingray/scanner/lybid/LybidServiceMetaInfo.h>
#include <stingray/scanner/tricolor/TricolorServiceMetaInfo.h>
#include <stingray/streams/PlaybackStreamContent.h>
#include <stingray/streams/RecordStreamContent.h>
#include <stingray/streams/RecordStreamMetaInfo.h>
#include <stingray/tuners/dvbs/Antenna.h>
#include <stingray/tuners/dvbs/DefaultDVBSTransport.h>
#include <stingray/tuners/dvbs/Satellite.h>
#include <stingray/tuners/dvbt/DVBTTransport.h>
#include <stingray/tuners/ip/TsOverIpTransport.h>
#include <stingray/update/DefaultUpdateRequirement.h>
#include <stingray/update/system/CheckImageSignature.h>
#include <stingray/update/system/EraseFlashPartition.h>
#include <stingray/update/system/WriteFlashPartition.h>

/* WARNING! This is autogenerated file, DO NOT EDIT! */

namespace stingray { namespace Detail
{
	void Factory::RegisterTypes()
	{
#ifdef BUILD_SHARED_LIB
		/*nothing*/
#else
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AppChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::app::AppChannelPtr>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ChannelList);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::CinemaHallScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ContinuousScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::DeferredStandby);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::InfiniteScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AutoFilter);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::User);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscription);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscriptionProvider);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HDMIConfig);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(InMemoryImageMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MediaInfoBase);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Mp3MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(flv::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mpeg::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DHCPInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(IgnoredInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LinkLocalInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ManualInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(AgeRating);
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::EmuServiceId);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::RadioChannel);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::StreamDescriptor);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::TVChannel);
#endif
		TOOLKIT_REGISTER_CLASS_EXPLICIT(FileSystemRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(rpc::UrlObjectId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBServiceId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBTBandInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegRadioChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegService);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegTVChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegAudioStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegDataCarouselStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegPcrStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextBasedSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegVideoStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DreCasGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::ServiceId>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlaybackStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Antenna);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBSTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Satellite);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TsOverIpTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMinimalVersionRequirement);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CheckImageSignature);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(EraseFlashPartition);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(WriteFlashPartition);
#endif
	}
}}
<commit_msg>Added IFactoryObject to LockedTunerState and similar classes to fix serialization<commit_after>#include <stingray/toolkit/Factory.h>

#include <stingray/toolkit/any.h>

#include <stingray/app/application_context/AppChannel.h>
#include <stingray/app/application_context/ChannelList.h>
#include <stingray/app/scheduler/ScheduledEvents.h>
#include <stingray/app/tests/AutoFilter.h>
#include <stingray/app/zapper/User.h>
#include <stingray/ca/BasicSubscription.h>
#include <stingray/hdmi/IHDMI.h>
#include <stingray/media/ImageFileMediaData.h>
#include <stingray/media/MediaInfoBase.h>
#include <stingray/media/Mp3MediaInfo.h>
#include <stingray/media/formats/flv/MediaInfo.h>
#include <stingray/media/formats/mp4/MediaInfo.h>
#include <stingray/mpeg/Stream.h>
#include <stingray/net/DHCPInterfaceConfiguration.h>
#include <stingray/net/IgnoredInterfaceConfiguration.h>
#include <stingray/net/LinkLocalInterfaceConfiguration.h>
#include <stingray/net/ManualInterfaceConfiguration.h>
#include <stingray/parentalcontrol/AgeRating.h>
#ifdef PLATFORM_EMU
#	include <stingray/platform/emu/scanner/Channel.h>
#endif
#include <stingray/records/FileSystemRecord.h>
#include <stingray/rpc/UrlObjectId.h>
#include <stingray/scanner/DVBServiceId.h>
#include <stingray/scanner/DefaultDVBTBandInfo.h>
#include <stingray/scanner/DefaultMpegService.h>
#include <stingray/scanner/DefaultMpegStreamDescriptor.h>
#include <stingray/scanner/DefaultScanParams.h>
#include <stingray/scanner/DreCasGeographicRegion.h>
#include <stingray/scanner/IServiceId.h>
#include <stingray/scanner/LybidScanParams.h>
#include <stingray/scanner/TricolorGeographicRegion.h>
#include <stingray/scanner/TricolorScanParams.h>
#include <stingray/scanner/lybid/LybidServiceMetaInfo.h>
#include <stingray/scanner/tricolor/TricolorServiceMetaInfo.h>
#include <stingray/streams/PlaybackStreamContent.h>
#include <stingray/streams/RecordStreamContent.h>
#include <stingray/streams/RecordStreamMetaInfo.h>
#include <stingray/tuners/TunerState.h>
#include <stingray/tuners/dvbs/Antenna.h>
#include <stingray/tuners/dvbs/DefaultDVBSTransport.h>
#include <stingray/tuners/dvbs/Satellite.h>
#include <stingray/tuners/dvbt/DVBTTransport.h>
#include <stingray/tuners/ip/TsOverIpTransport.h>
#include <stingray/update/DefaultUpdateRequirement.h>
#include <stingray/update/system/CheckImageSignature.h>
#include <stingray/update/system/EraseFlashPartition.h>
#include <stingray/update/system/WriteFlashPartition.h>

/* WARNING! This is autogenerated file, DO NOT EDIT! */

namespace stingray { namespace Detail
{
	void Factory::RegisterTypes()
	{
#ifdef BUILD_SHARED_LIB
		/*nothing*/
#else
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AppChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::app::AppChannelPtr>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ChannelList);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::CinemaHallScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ContinuousScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::DeferredStandby);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::InfiniteScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AutoFilter);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::User);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscription);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscriptionProvider);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HDMIConfig);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(InMemoryImageMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MediaInfoBase);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Mp3MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(flv::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mpeg::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DHCPInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(IgnoredInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LinkLocalInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ManualInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(AgeRating);
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::EmuServiceId);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::RadioChannel);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::StreamDescriptor);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::TVChannel);
#endif
		TOOLKIT_REGISTER_CLASS_EXPLICIT(FileSystemRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(rpc::UrlObjectId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBServiceId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBTBandInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegRadioChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegService);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegTVChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegAudioStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegDataCarouselStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegPcrStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextBasedSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegVideoStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DreCasGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::ServiceId>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlaybackStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CircuitedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(UnlockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Antenna);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBSTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Satellite);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TsOverIpTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMinimalVersionRequirement);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CheckImageSignature);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(EraseFlashPartition);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(WriteFlashPartition);
#endif
	}
}}
<|endoftext|>


<commit_before>/*
* Runtime CPU detection for x86
* (C) 2009,2010,2013,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/internal/cpuid.h>
#include <botan/mem_ops.h>
#include <botan/internal/loadstor.h>

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
  #include <intrin.h>
#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
  #include <ia32intrin.h>
#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
  #include <cpuid.h>
#endif

#endif

namespace Botan {

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

namespace {

void invoke_cpuid(uint32_t type, uint32_t out[4])
   {
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) || defined(BOTAN_BUILD_COMPILER_IS_INTEL)
   __cpuid((int*)out, type);

#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && defined(BOTAN_USE_GCC_INLINE_ASM)
   asm("cpuid\n\t"
       : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3])
       : "0" (type));

#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
   __get_cpuid(type, out, out+1, out+2, out+3);
#else
   #warning "No way of calling x86 cpuid instruction for this compiler"
   clear_mem(out, 4);
#endif
   }

void invoke_cpuid_sublevel(uint32_t type, uint32_t level, uint32_t out[4])
   {
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   __cpuidex((int*)out, type, level);

#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
   __cpuidex((int*)out, type, level);

#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && defined(BOTAN_USE_GCC_INLINE_ASM)
   asm("cpuid\n\t"
       : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3])     \
       : "0" (type), "2" (level));

#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
   __cpuid_count(type, level, out[0], out[1], out[2], out[3]);
#else
   #warning "No way of calling x86 cpuid instruction for this compiler"
   clear_mem(out, 4);
#endif
   }

}

uint64_t CPUID::CPUID_Data::detect_cpu_features(size_t* cache_line_size)
   {
   uint64_t features_detected = 0;
   uint32_t cpuid[4] = { 0 };

   // CPUID 0: vendor identification, max sublevel
   invoke_cpuid(0, cpuid);

   const uint32_t max_supported_sublevel = cpuid[0];

   const uint32_t INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
   const uint32_t AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
   const bool is_intel = same_mem(cpuid + 1, INTEL_CPUID, 3);
   const bool is_amd = same_mem(cpuid + 1, AMD_CPUID, 3);

   if(max_supported_sublevel >= 1)
      {
      // CPUID 1: feature bits
      invoke_cpuid(1, cpuid);
      const uint64_t flags0 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[3];

      enum x86_CPUID_1_bits : uint64_t {
         RDTSC = (1ULL << 4),
         SSE2 = (1ULL << 26),
         CLMUL = (1ULL << 33),
         SSSE3 = (1ULL << 41),
         SSE41 = (1ULL << 51),
         SSE42 = (1ULL << 52),
         AESNI = (1ULL << 57),
         RDRAND = (1ULL << 62)
      };

      if(flags0 & x86_CPUID_1_bits::RDTSC)
         features_detected |= CPUID::CPUID_RDTSC_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE2)
         features_detected |= CPUID::CPUID_SSE2_BIT;
      if(flags0 & x86_CPUID_1_bits::CLMUL)
         features_detected |= CPUID::CPUID_CLMUL_BIT;
      if(flags0 & x86_CPUID_1_bits::SSSE3)
         features_detected |= CPUID::CPUID_SSSE3_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE41)
         features_detected |= CPUID::CPUID_SSE41_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE42)
         features_detected |= CPUID::CPUID_SSE42_BIT;
      if(flags0 & x86_CPUID_1_bits::AESNI)
         features_detected |= CPUID::CPUID_AESNI_BIT;
      if(flags0 & x86_CPUID_1_bits::RDRAND)
         features_detected |= CPUID::CPUID_RDRAND_BIT;
      }

   if(is_intel)
      {
      // Intel cache line size is in cpuid(1) output
      *cache_line_size = 8 * get_byte<2>(cpuid[1]);
      }
   else if(is_amd)
      {
      // AMD puts it in vendor zone
      invoke_cpuid(0x80000005, cpuid);
      *cache_line_size = get_byte<3>(cpuid[2]);
      }

   if(max_supported_sublevel >= 7)
      {
      clear_mem(cpuid, 4);
      invoke_cpuid_sublevel(7, 0, cpuid);

      enum x86_CPUID_7_bits : uint64_t {
         BMI1 = (1ULL << 3),
         AVX2 = (1ULL << 5),
         BMI2 = (1ULL << 8),
         AVX512_F = (1ULL << 16),
         AVX512_DQ = (1ULL << 17),
         RDSEED = (1ULL << 18),
         ADX = (1ULL << 19),
         AVX512_IFMA = (1ULL << 21),
         SHA = (1ULL << 29),
         AVX512_BW = (1ULL << 30),
         AVX512_VL = (1ULL << 31),
         AVX512_VBMI = (1ULL << 33),
         AVX512_VBMI2 = (1ULL << 38),
         AVX512_VAES = (1ULL << 41),
         AVX512_VCLMUL = (1ULL << 42),
         AVX512_VBITALG = (1ULL << 44),
      };

      const uint64_t flags7 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[1];

      if(flags7 & x86_CPUID_7_bits::AVX2)
         features_detected |= CPUID::CPUID_AVX2_BIT;
      if(flags7 & x86_CPUID_7_bits::BMI1)
         {
         features_detected |= CPUID::CPUID_BMI1_BIT;
         /*
         We only set the BMI2 bit if BMI1 is also supported, so BMI2
         code can safely use both extensions. No known processor
         implements BMI2 but not BMI1.
         */
         if(flags7 & x86_CPUID_7_bits::BMI2)
            {
            features_detected |= CPUID::CPUID_BMI2_BIT;

            /*
            Up until Zen3, AMD CPUs with BMI2 support had microcoded
            pdep/pext, which works but is very slow.

            TODO: check for Zen3 here
            */
            if(is_intel)
               {
               features_detected |= CPUID::CPUID_FAST_PDEP_BIT;
               }
            }
         }

      if(flags7 & x86_CPUID_7_bits::AVX512_F)
         {
         features_detected |= CPUID::CPUID_AVX512F_BIT;

         if(flags7 & x86_CPUID_7_bits::AVX512_DQ)
            features_detected |= CPUID::CPUID_AVX512DQ_BIT;
         if(flags7 & x86_CPUID_7_bits::AVX512_BW)
            features_detected |= CPUID::CPUID_AVX512BW_BIT;

         const uint64_t ICELAKE_FLAGS =
            x86_CPUID_7_bits::AVX512_F |
            x86_CPUID_7_bits::AVX512_DQ |
            x86_CPUID_7_bits::AVX512_IFMA |
            x86_CPUID_7_bits::AVX512_BW |
            x86_CPUID_7_bits::AVX512_VL |
            x86_CPUID_7_bits::AVX512_VBMI |
            x86_CPUID_7_bits::AVX512_VBMI2 |
            x86_CPUID_7_bits::AVX512_VBITALG;

         if((flags7 & ICELAKE_FLAGS) == ICELAKE_FLAGS)
            features_detected |= CPUID::CPUID_AVX512_ICL_BIT;

         if(flags7 & x86_CPUID_7_bits::AVX512_VAES)
            features_detected |= CPUID::CPUID_AVX512_AES_BIT;
         if(flags7 & x86_CPUID_7_bits::AVX512_VCLMUL)
            features_detected |= CPUID::CPUID_AVX512_CLMUL_BIT;
         }

      if(flags7 & x86_CPUID_7_bits::RDSEED)
         features_detected |= CPUID::CPUID_RDSEED_BIT;
      if(flags7 & x86_CPUID_7_bits::ADX)
         features_detected |= CPUID::CPUID_ADX_BIT;
      if(flags7 & x86_CPUID_7_bits::SHA)
         features_detected |= CPUID::CPUID_SHA_BIT;
      }

   /*
   * If we don't have access to CPUID, we can still safely assume that
   * any x86-64 processor has SSE2 and RDTSC
   */
#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
   if(features_detected == 0)
      {
      features_detected |= CPUID::CPUID_SSE2_BIT;
      features_detected |= CPUID::CPUID_RDTSC_BIT;
      }
#endif

   return features_detected;
   }

#endif

}
<commit_msg>Revamp x86 CPUID<commit_after>/*
* Runtime CPU detection for x86
* (C) 2009,2010,2013,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/internal/cpuid.h>
#include <botan/mem_ops.h>
#include <botan/internal/loadstor.h>

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
  #include <intrin.h>
#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
  #include <ia32intrin.h>
#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
  #include <cpuid.h>
#endif

#endif

namespace Botan {

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

namespace {

void invoke_cpuid(uint32_t type, uint32_t out[4])
   {
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) || defined(BOTAN_BUILD_COMPILER_IS_INTEL)
   __cpuid((int*)out, type);

#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
   __get_cpuid(type, out, out+1, out+2, out+3);

#elif defined(BOTAN_USE_GCC_INLINE_ASM)
   asm("cpuid\n\t"
       : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3])
       : "0" (type));

#else
   #warning "No way of calling x86 cpuid instruction for this compiler"
   clear_mem(out, 4);
#endif
   }

void invoke_cpuid_sublevel(uint32_t type, uint32_t level, uint32_t out[4])
   {
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
   __cpuidex((int*)out, type, level);

#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
   __cpuid_count(type, level, out[0], out[1], out[2], out[3]);

#elif defined(BOTAN_USE_GCC_INLINE_ASM)
   asm("cpuid\n\t"
       : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3])     \
       : "0" (type), "2" (level));

#else
   #warning "No way of calling x86 cpuid instruction for this compiler"
   clear_mem(out, 4);
#endif
   }

}

uint64_t CPUID::CPUID_Data::detect_cpu_features(size_t* cache_line_size)
   {
   uint64_t features_detected = 0;
   uint32_t cpuid[4] = { 0 };

   // CPUID 0: vendor identification, max sublevel
   invoke_cpuid(0, cpuid);

   const uint32_t max_supported_sublevel = cpuid[0];

   const uint32_t INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
   const uint32_t AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
   const bool is_intel = same_mem(cpuid + 1, INTEL_CPUID, 3);
   const bool is_amd = same_mem(cpuid + 1, AMD_CPUID, 3);

   if(max_supported_sublevel >= 1)
      {
      // CPUID 1: feature bits
      invoke_cpuid(1, cpuid);
      const uint64_t flags0 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[3];

      enum x86_CPUID_1_bits : uint64_t {
         RDTSC = (1ULL << 4),
         SSE2 = (1ULL << 26),
         CLMUL = (1ULL << 33),
         SSSE3 = (1ULL << 41),
         SSE41 = (1ULL << 51),
         SSE42 = (1ULL << 52),
         AESNI = (1ULL << 57),
         RDRAND = (1ULL << 62)
      };

      if(flags0 & x86_CPUID_1_bits::RDTSC)
         features_detected |= CPUID::CPUID_RDTSC_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE2)
         features_detected |= CPUID::CPUID_SSE2_BIT;
      if(flags0 & x86_CPUID_1_bits::CLMUL)
         features_detected |= CPUID::CPUID_CLMUL_BIT;
      if(flags0 & x86_CPUID_1_bits::SSSE3)
         features_detected |= CPUID::CPUID_SSSE3_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE41)
         features_detected |= CPUID::CPUID_SSE41_BIT;
      if(flags0 & x86_CPUID_1_bits::SSE42)
         features_detected |= CPUID::CPUID_SSE42_BIT;
      if(flags0 & x86_CPUID_1_bits::AESNI)
         features_detected |= CPUID::CPUID_AESNI_BIT;
      if(flags0 & x86_CPUID_1_bits::RDRAND)
         features_detected |= CPUID::CPUID_RDRAND_BIT;
      }

   if(is_intel)
      {
      // Intel cache line size is in cpuid(1) output
      *cache_line_size = 8 * get_byte<2>(cpuid[1]);
      }
   else if(is_amd)
      {
      // AMD puts it in vendor zone
      invoke_cpuid(0x80000005, cpuid);
      *cache_line_size = get_byte<3>(cpuid[2]);
      }

   if(max_supported_sublevel >= 7)
      {
      clear_mem(cpuid, 4);
      invoke_cpuid_sublevel(7, 0, cpuid);

      enum x86_CPUID_7_bits : uint64_t {
         BMI1 = (1ULL << 3),
         AVX2 = (1ULL << 5),
         BMI2 = (1ULL << 8),
         AVX512_F = (1ULL << 16),
         AVX512_DQ = (1ULL << 17),
         RDSEED = (1ULL << 18),
         ADX = (1ULL << 19),
         AVX512_IFMA = (1ULL << 21),
         SHA = (1ULL << 29),
         AVX512_BW = (1ULL << 30),
         AVX512_VL = (1ULL << 31),
         AVX512_VBMI = (1ULL << 33),
         AVX512_VBMI2 = (1ULL << 38),
         AVX512_VAES = (1ULL << 41),
         AVX512_VCLMUL = (1ULL << 42),
         AVX512_VBITALG = (1ULL << 44),
      };

      const uint64_t flags7 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[1];

      if(flags7 & x86_CPUID_7_bits::AVX2)
         features_detected |= CPUID::CPUID_AVX2_BIT;
      if(flags7 & x86_CPUID_7_bits::BMI1)
         {
         features_detected |= CPUID::CPUID_BMI1_BIT;
         /*
         We only set the BMI2 bit if BMI1 is also supported, so BMI2
         code can safely use both extensions. No known processor
         implements BMI2 but not BMI1.
         */
         if(flags7 & x86_CPUID_7_bits::BMI2)
            {
            features_detected |= CPUID::CPUID_BMI2_BIT;

            /*
            Up until Zen3, AMD CPUs with BMI2 support had microcoded
            pdep/pext, which works but is very slow.

            TODO: check for Zen3 here
            */
            if(is_intel)
               {
               features_detected |= CPUID::CPUID_FAST_PDEP_BIT;
               }
            }
         }

      if(flags7 & x86_CPUID_7_bits::AVX512_F)
         {
         features_detected |= CPUID::CPUID_AVX512F_BIT;

         if(flags7 & x86_CPUID_7_bits::AVX512_DQ)
            features_detected |= CPUID::CPUID_AVX512DQ_BIT;
         if(flags7 & x86_CPUID_7_bits::AVX512_BW)
            features_detected |= CPUID::CPUID_AVX512BW_BIT;

         const uint64_t ICELAKE_FLAGS =
            x86_CPUID_7_bits::AVX512_F |
            x86_CPUID_7_bits::AVX512_DQ |
            x86_CPUID_7_bits::AVX512_IFMA |
            x86_CPUID_7_bits::AVX512_BW |
            x86_CPUID_7_bits::AVX512_VL |
            x86_CPUID_7_bits::AVX512_VBMI |
            x86_CPUID_7_bits::AVX512_VBMI2 |
            x86_CPUID_7_bits::AVX512_VBITALG;

         if((flags7 & ICELAKE_FLAGS) == ICELAKE_FLAGS)
            features_detected |= CPUID::CPUID_AVX512_ICL_BIT;

         if(flags7 & x86_CPUID_7_bits::AVX512_VAES)
            features_detected |= CPUID::CPUID_AVX512_AES_BIT;
         if(flags7 & x86_CPUID_7_bits::AVX512_VCLMUL)
            features_detected |= CPUID::CPUID_AVX512_CLMUL_BIT;
         }

      if(flags7 & x86_CPUID_7_bits::RDSEED)
         features_detected |= CPUID::CPUID_RDSEED_BIT;
      if(flags7 & x86_CPUID_7_bits::ADX)
         features_detected |= CPUID::CPUID_ADX_BIT;
      if(flags7 & x86_CPUID_7_bits::SHA)
         features_detected |= CPUID::CPUID_SHA_BIT;
      }

   /*
   * If we don't have access to CPUID, we can still safely assume that
   * any x86-64 processor has SSE2 and RDTSC
   */
#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
   if(features_detected == 0)
      {
      features_detected |= CPUID::CPUID_SSE2_BIT;
      features_detected |= CPUID::CPUID_RDTSC_BIT;
      }
#endif

   return features_detected;
   }

#endif

}
<|endoftext|>