<commit_before>#include "proctor/scanning_model_source.h"

#include <cstdio>
#include <vector>
#include <sstream>
#include <fstream>

#include <vtkCellArray.h>
#include <vtkFloatArray.h>
#include <vtkPoints.h>
#include <vtkSmartPointer.h>

#include <pcl/filters/filter.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/ply_io.h>
#include <pcl/common/eigen.h>
#include <pcl/common/transforms.h>
#include <pcl/common/common.h>

#include "proctor/PSBClaParse.h"

namespace pcl
{

  namespace proctor
  {

    const float theta_start = M_PI / 12;
    const float theta_step = 0.0f;
    const int theta_count = 1;
    const float phi_start = 0.0f;
    const float phi_step = M_PI / 6;
    const int phi_count = 12;
    const float theta_min = 0.0f;
    const float theta_max = M_PI / 6;
    const float phi_min = 0.0f;
    const float phi_max = M_PI * 2;

    IndicesPtr
    ScanningModelSource::randomSubset(int n, int r)
    {
      IndicesPtr subset (new std::vector<int>());
      std::vector<int> bag (n);
      for (int i = 0; i < n; i++) bag[i] = i;
      int edge = n;
      subset->resize(r);
      for (int i = 0; i < r; i++) {
        int pick = rand() % edge;
        (*subset)[i] = bag[pick];
        bag[pick] = bag[--edge];
      }
      return subset;
    }

    // TODO Finish this
    void
    ScanningModelSource::pickUniqueModels(std::vector<int>& ids)
    {
      std::stringstream path;
      path << dir_ << "/classification/v1/base/test.cla";

      PSBCategoryList* list = parseFile((char *) (path.str().c_str()), false);

      ids.clear();
      for (int i = 0; i < list->_numCategories; i++)
      {
        PSBCategory *category = list->_categories[i];

        if (category->_numModels > 0)
        {
          // Pick the first model from each category
          char* model = category->_models[0];
          ids.push_back(atoi(model));
        }
      }

    }

    void
    ScanningModelSource::loadModels()
    {
      std::vector<int> ids;
      pickUniqueModels(ids);

      //int max_models = 1814;
      //srand(0);
      //IndicesPtr model_subset = randomSubset(max_models, max_models);

      //for (int mi = 0; mi < ids.size(); mi++) {
      for (auto it = ids.begin(); it != ids.end(); ++it)
      {
        int id = *it;
        std::stringstream path;
        FILE *file;
        int vertices, faces, edges;

        // Put model in map
        Model* new_model = new Model;
        std::stringstream ss;
        ss << name_ << id;
        std::string new_id = ss.str();
        new_model->id = new_id;

        // read mesh
        path << dir_ << "/db/" << id / 100 << "/m" << id << "/m" << id << ".off";
        file = fopen(path.str ().c_str (), "r");

        if (file == NULL) {
          cerr << "Could not find " << path.str() << endl;
          continue;
          //exit(-1);
        }

        int line = 1;

        // read header
        if (fscanf(file, "OFF\n%d %d %d\n", &vertices, &faces, &edges) != 3) {
          cerr << "invalid OFF header in file " << path << endl;
          exit(-1);
        } else {
          line += 2;
        }

        // read vertices
        vtkFloatArray *fa = vtkFloatArray::New();
        fa->SetNumberOfComponents(3);
        float (*v)[3] = reinterpret_cast<float (*)[3]>(fa->WritePointer(0, 3 * vertices));
        for (int j = 0; j < vertices; j++) {
          if (fscanf(file, "%f %f %f\n", &v[j][0], &v[j][1], &v[j][2]) != 3) {
            cerr << "invalid vertex in file " << path << " on line " << line << endl;
            exit(-1);
          } else {
            ++line;
          }
        }
        vtkPoints *p = vtkPoints::New();
        p->SetData(fa); fa->Delete();

        // read faces
        vtkCellArray *ca = vtkCellArray::New();
        vtkIdType (*f)[4] = reinterpret_cast<vtkIdType (*)[4]>(ca->WritePointer(faces, 4 * faces));
        for (int j = 0; j < faces; j++) {
          f[j][0] = 3; // only supports triangles...
          if (fscanf (file, "3 %lld %lld %lld\n", (long long int*)&f[j][1], (long long int*)&f[j][2], (long long int*)&f[j][3]) != 3)
          {
            cerr << "invalid face in file " << path << " on line " << line << endl;
            exit(-1);
          } else {
            ++line;
          }
        }

        fclose(file);

        vtkPolyData* new_mesh = vtkPolyData::New();
        new_mesh->SetPoints(p);// p->Delete();
        new_mesh->SetPolys(ca);// ca->Delete();

        new_model->mesh = new_mesh->GetProducerPort();

        // read metadata
        path.str ("");
        path << dir_ << "/db/" << id / 100 << "/m" << id << "/m" << id << "_info.txt";
        file = fopen(path.str ().c_str (), "r");
        while (!feof(file)) {
          char buf[256];
          if (fgets(buf, sizeof(buf), file) != NULL) {
            if (!strncmp("center: ", buf, 8)) {
              if (sscanf(buf, "center: (%f,%f,%f)\n", &new_model->cx, &new_model->cy, &new_model->cz) != 3) {
                cerr << "invalid centroid in file " << path << endl;
                cerr << buf;
                exit(-1);
              }
            } else if (!strncmp("scale: ", buf, 7)) {
              if (sscanf(buf, "scale: %f\n", &new_model->scale) != 1) {
                cerr << "invalid scale in file " << path << endl;
                cerr << buf;
                exit(-1);
              }
            }
          }
        } // end while over info lines
        fclose(file);

        models_[new_id] = *new_model;
      } // end for over models
    }

    void
    ScanningModelSource::getModelIDs(std::vector<std::string> &output)
    {
      std::map<std::string, Model>::iterator it;
      output.clear();

      for ( it = models_.begin() ; it != models_.end(); it++ ) {
        output.push_back((*it).first);
      }
      //output.push_back("princeton1298");
      //output.push_back("princeton1303");
      //output.push_back("princeton48");
      //output.push_back("princeton97");
      //output.push_back("princeton99");
      //output.push_back("princeton70");
      //output.push_back("princeton725");
      //output.push_back("princeton688");
      //output.push_back("princeton1779");
      //output.push_back("princeton382");
      //output.push_back("princeton398");
      //output.push_back("princeton407");

      sort(output.begin(), output.end());
    }

    PointCloud<PointNormal>::Ptr
    ScanningModelSource::getTrainingModel(std::string model_id)
    {
      PointCloud<PointNormal>::Ptr full_cloud(new PointCloud<PointNormal>());

      for (int ti = 0; ti < theta_count; ti++) {
        for (int pi = 0; pi < phi_count; pi++) {
          float theta = Scanner::theta_start + ti * Scanner::theta_step;
          float phi = Scanner::phi_start + pi * Scanner::phi_step;

          *full_cloud += *Scanner::getCloudCached(theta, phi, models_[model_id]);
          flush(cout << '.');
        }
      }
      cout << endl;

      // Remove NaNs
      PointCloud<PointNormal>::Ptr dense_cloud (new PointCloud<PointNormal>());

      std::vector<int> index;
      pcl::removeNaNFromPointCloud<PointNormal>(*full_cloud, *dense_cloud, index);

      PointCloud<PointNormal>::Ptr cloud_subsampled (new PointCloud<PointNormal> ());
      VoxelGrid<PointNormal> subsampling_filter;
      subsampling_filter.setInputCloud(dense_cloud);
      subsampling_filter.setLeafSize(0.001, 0.001, 0.001);
      subsampling_filter.filter(*cloud_subsampled);

      assert(cloud_subsampled->is_dense == true);

      return cloud_subsampled;
    }

    PointCloud<PointNormal>::Ptr
    ScanningModelSource::getTestModel(std::string model_id)
    {
      float theta = (*theta_gen)();
      float phi = (*phi_gen)();

      cout << "Theta: " << theta << endl;
      cout << "Phi: " << phi << endl;

      PointCloud<PointNormal>::Ptr test_scan = Scanner::getCloudCached(theta, phi, models_[model_id]);
      Eigen::Affine3f t;
      getTransformation(0, 0, 0, M_PI, 0.5, 1.5, t);
      PointCloud<PointNormal>::Ptr rotated_scan(new PointCloud<PointNormal>());
      transformPointCloudWithNormals(*test_scan, *rotated_scan, t);
      //return test_scan;
      return rotated_scan;
    }

    void
    ScanningModelSource::resetTestGenerator()
    {
      rng_.seed(0);
      theta_u = boost::uniform_real<float>(theta_min, theta_max);
      phi_u = boost::uniform_real<float>(phi_min, phi_max);
      theta_gen = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> >(rng_, theta_u);
      phi_gen = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> >(rng_, phi_u);
    }
  }

}
<commit_msg>auto->int<commit_after>#include "proctor/scanning_model_source.h"

#include <cstdio>
#include <vector>
#include <sstream>
#include <fstream>

#include <vtkCellArray.h>
#include <vtkFloatArray.h>
#include <vtkPoints.h>
#include <vtkSmartPointer.h>

#include <pcl/filters/filter.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/ply_io.h>
#include <pcl/common/eigen.h>
#include <pcl/common/transforms.h>
#include <pcl/common/common.h>

#include "proctor/PSBClaParse.h"

namespace pcl
{

  namespace proctor
  {

    const float theta_start = M_PI / 12;
    const float theta_step = 0.0f;
    const int theta_count = 1;
    const float phi_start = 0.0f;
    const float phi_step = M_PI / 6;
    const int phi_count = 12;
    const float theta_min = 0.0f;
    const float theta_max = M_PI / 6;
    const float phi_min = 0.0f;
    const float phi_max = M_PI * 2;

    IndicesPtr
    ScanningModelSource::randomSubset(int n, int r)
    {
      IndicesPtr subset (new std::vector<int>());
      std::vector<int> bag (n);
      for (int i = 0; i < n; i++) bag[i] = i;
      int edge = n;
      subset->resize(r);
      for (int i = 0; i < r; i++) {
        int pick = rand() % edge;
        (*subset)[i] = bag[pick];
        bag[pick] = bag[--edge];
      }
      return subset;
    }

    // TODO Finish this
    void
    ScanningModelSource::pickUniqueModels(std::vector<int>& ids)
    {
      std::stringstream path;
      path << dir_ << "/classification/v1/base/test.cla";

      PSBCategoryList* list = parseFile((char *) (path.str().c_str()), false);

      ids.clear();
      for (int i = 0; i < list->_numCategories; i++)
      {
        PSBCategory *category = list->_categories[i];

        if (category->_numModels > 0)
        {
          // Pick the first model from each category
          char* model = category->_models[0];
          ids.push_back(atoi(model));
        }
      }

    }

    void
    ScanningModelSource::loadModels()
    {
      std::vector<int> ids;
      pickUniqueModels(ids);

      //int max_models = 1814;
      //srand(0);
      //IndicesPtr model_subset = randomSubset(max_models, max_models);

      //for (int mi = 0; mi < ids.size(); mi++) {
      for (int it = ids.begin(); it != ids.end(); ++it)
      {
        int id = *it;
        std::stringstream path;
        FILE *file;
        int vertices, faces, edges;

        // Put model in map
        Model* new_model = new Model;
        std::stringstream ss;
        ss << name_ << id;
        std::string new_id = ss.str();
        new_model->id = new_id;

        // read mesh
        path << dir_ << "/db/" << id / 100 << "/m" << id << "/m" << id << ".off";
        file = fopen(path.str ().c_str (), "r");

        if (file == NULL) {
          cerr << "Could not find " << path.str() << endl;
          continue;
          //exit(-1);
        }

        int line = 1;

        // read header
        if (fscanf(file, "OFF\n%d %d %d\n", &vertices, &faces, &edges) != 3) {
          cerr << "invalid OFF header in file " << path << endl;
          exit(-1);
        } else {
          line += 2;
        }

        // read vertices
        vtkFloatArray *fa = vtkFloatArray::New();
        fa->SetNumberOfComponents(3);
        float (*v)[3] = reinterpret_cast<float (*)[3]>(fa->WritePointer(0, 3 * vertices));
        for (int j = 0; j < vertices; j++) {
          if (fscanf(file, "%f %f %f\n", &v[j][0], &v[j][1], &v[j][2]) != 3) {
            cerr << "invalid vertex in file " << path << " on line " << line << endl;
            exit(-1);
          } else {
            ++line;
          }
        }
        vtkPoints *p = vtkPoints::New();
        p->SetData(fa); fa->Delete();

        // read faces
        vtkCellArray *ca = vtkCellArray::New();
        vtkIdType (*f)[4] = reinterpret_cast<vtkIdType (*)[4]>(ca->WritePointer(faces, 4 * faces));
        for (int j = 0; j < faces; j++) {
          f[j][0] = 3; // only supports triangles...
          if (fscanf (file, "3 %lld %lld %lld\n", (long long int*)&f[j][1], (long long int*)&f[j][2], (long long int*)&f[j][3]) != 3)
          {
            cerr << "invalid face in file " << path << " on line " << line << endl;
            exit(-1);
          } else {
            ++line;
          }
        }

        fclose(file);

        vtkPolyData* new_mesh = vtkPolyData::New();
        new_mesh->SetPoints(p);// p->Delete();
        new_mesh->SetPolys(ca);// ca->Delete();

        new_model->mesh = new_mesh->GetProducerPort();

        // read metadata
        path.str ("");
        path << dir_ << "/db/" << id / 100 << "/m" << id << "/m" << id << "_info.txt";
        file = fopen(path.str ().c_str (), "r");
        while (!feof(file)) {
          char buf[256];
          if (fgets(buf, sizeof(buf), file) != NULL) {
            if (!strncmp("center: ", buf, 8)) {
              if (sscanf(buf, "center: (%f,%f,%f)\n", &new_model->cx, &new_model->cy, &new_model->cz) != 3) {
                cerr << "invalid centroid in file " << path << endl;
                cerr << buf;
                exit(-1);
              }
            } else if (!strncmp("scale: ", buf, 7)) {
              if (sscanf(buf, "scale: %f\n", &new_model->scale) != 1) {
                cerr << "invalid scale in file " << path << endl;
                cerr << buf;
                exit(-1);
              }
            }
          }
        } // end while over info lines
        fclose(file);

        models_[new_id] = *new_model;
      } // end for over models
    }

    void
    ScanningModelSource::getModelIDs(std::vector<std::string> &output)
    {
      std::map<std::string, Model>::iterator it;
      output.clear();

      for ( it = models_.begin() ; it != models_.end(); it++ ) {
        output.push_back((*it).first);
      }
      //output.push_back("princeton1298");
      //output.push_back("princeton1303");
      //output.push_back("princeton48");
      //output.push_back("princeton97");
      //output.push_back("princeton99");
      //output.push_back("princeton70");
      //output.push_back("princeton725");
      //output.push_back("princeton688");
      //output.push_back("princeton1779");
      //output.push_back("princeton382");
      //output.push_back("princeton398");
      //output.push_back("princeton407");

      sort(output.begin(), output.end());
    }

    PointCloud<PointNormal>::Ptr
    ScanningModelSource::getTrainingModel(std::string model_id)
    {
      PointCloud<PointNormal>::Ptr full_cloud(new PointCloud<PointNormal>());

      for (int ti = 0; ti < theta_count; ti++) {
        for (int pi = 0; pi < phi_count; pi++) {
          float theta = Scanner::theta_start + ti * Scanner::theta_step;
          float phi = Scanner::phi_start + pi * Scanner::phi_step;

          *full_cloud += *Scanner::getCloudCached(theta, phi, models_[model_id]);
          flush(cout << '.');
        }
      }
      cout << endl;

      // Remove NaNs
      PointCloud<PointNormal>::Ptr dense_cloud (new PointCloud<PointNormal>());

      std::vector<int> index;
      pcl::removeNaNFromPointCloud<PointNormal>(*full_cloud, *dense_cloud, index);

      PointCloud<PointNormal>::Ptr cloud_subsampled (new PointCloud<PointNormal> ());
      VoxelGrid<PointNormal> subsampling_filter;
      subsampling_filter.setInputCloud(dense_cloud);
      subsampling_filter.setLeafSize(0.001, 0.001, 0.001);
      subsampling_filter.filter(*cloud_subsampled);

      assert(cloud_subsampled->is_dense == true);

      return cloud_subsampled;
    }

    PointCloud<PointNormal>::Ptr
    ScanningModelSource::getTestModel(std::string model_id)
    {
      float theta = (*theta_gen)();
      float phi = (*phi_gen)();

      cout << "Theta: " << theta << endl;
      cout << "Phi: " << phi << endl;

      PointCloud<PointNormal>::Ptr test_scan = Scanner::getCloudCached(theta, phi, models_[model_id]);
      Eigen::Affine3f t;
      getTransformation(0, 0, 0, M_PI, 0.5, 1.5, t);
      PointCloud<PointNormal>::Ptr rotated_scan(new PointCloud<PointNormal>());
      transformPointCloudWithNormals(*test_scan, *rotated_scan, t);
      //return test_scan;
      return rotated_scan;
    }

    void
    ScanningModelSource::resetTestGenerator()
    {
      rng_.seed(0);
      theta_u = boost::uniform_real<float>(theta_min, theta_max);
      phi_u = boost::uniform_real<float>(phi_min, phi_max);
      theta_gen = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> >(rng_, theta_u);
      phi_gen = new boost::variate_generator<boost::mt19937&, boost::uniform_real<float> >(rng_, phi_u);
    }
  }

}
<|endoftext|>


<commit_before>//-- includes -----
#include "ClientControllerView.h"
#include "PSMoveProtocol.pb.h"
#include <chrono>
#include <assert.h>

//-- pre-declarations -----

//-- constants -----
const PSMoveVector3 g_psmove_vector3_zero= {0.f, 0.f, 0.f};
const PSMoveVector3 *k_psmove_vector3_zero= &g_psmove_vector3_zero;

const PSMoveQuaternion g_psmove_quaternion_identity= {1.f, 0.f, 0.f, 0.f};
const PSMoveQuaternion *k_psmove_quaternion_identity= &g_psmove_quaternion_identity;

//-- prototypes ----
static void update_button_state(PSMoveButtonState &button, unsigned int button_bitmask, unsigned int button_bit);

//-- implementation -----

//-- ClientPSMoveView -----
void ClientPSMoveView::Clear()
{
    bValid= false;
    bIsTrackingEnabled= false;
    bIsCurrentlyTracking= false;

    Pose.Clear();

    TriangleButton= PSMoveButton_UP;
    CircleButton= PSMoveButton_UP;
    CrossButton= PSMoveButton_UP;
    SquareButton= PSMoveButton_UP;
    SelectButton= PSMoveButton_UP;
    StartButton= PSMoveButton_UP;
    PSButton= PSMoveButton_UP;
    MoveButton= PSMoveButton_UP;
    TriggerButton= PSMoveButton_UP;

    TriggerValue= 0;
}

void ClientPSMoveView::ApplyControllerDataFrame(const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    if (data_frame->isconnected())
    {
        const PSMoveProtocol::ControllerDataFrame_PSMoveState &psmove_data_frame= data_frame->psmove_state();

        this->bIsTrackingEnabled= psmove_data_frame.istrackingenabled();
        this->bIsCurrentlyTracking= psmove_data_frame.iscurrentlytracking();

        this->Pose.Orientation.w= psmove_data_frame.orientation().w();
        this->Pose.Orientation.x= psmove_data_frame.orientation().x();
        this->Pose.Orientation.y= psmove_data_frame.orientation().y();
        this->Pose.Orientation.z= psmove_data_frame.orientation().z();

        this->Pose.Position.x= psmove_data_frame.position().x();
        this->Pose.Position.y= psmove_data_frame.position().y();
        this->Pose.Position.z= psmove_data_frame.position().z();

        unsigned int button_bitmask= data_frame->button_down_bitmask();
        update_button_state(TriangleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIANGLE);
        update_button_state(CircleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CIRCLE);
        update_button_state(CrossButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CROSS);
        update_button_state(SquareButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_SQUARE);
        update_button_state(SelectButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_SELECT);
        update_button_state(StartButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_START);
        update_button_state(PSButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_PS);
        update_button_state(MoveButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_MOVE);
        update_button_state(TriggerButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIGGER);

        //###bwalker $TODO make sure this is in the range [0, 255]
        this->TriggerValue= static_cast<unsigned char>(psmove_data_frame.trigger_value());

        this->bValid= true;
    }
    else
    {
        Clear();
    }
}

//-- ClientPSNaviView -----
void ClientPSNaviView::Clear()
{
    bValid= false;

    L1Button= PSMoveButton_UP;
    L2Button= PSMoveButton_UP;
    L3Button= PSMoveButton_UP;
    CircleButton= PSMoveButton_UP;
    CrossButton= PSMoveButton_UP;
    PSButton= PSMoveButton_UP;
    TriggerButton= PSMoveButton_UP;
    DPadUpButton= PSMoveButton_UP;
    DPadRightButton= PSMoveButton_UP;
    DPadDownButton= PSMoveButton_UP;
    DPadLeftButton= PSMoveButton_UP;

    TriggerValue= 0;
    Stick_XAxis= 0x80;
    Stick_YAxis= 0x80;
}

void ClientPSNaviView::ApplyControllerDataFrame(const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    if (data_frame->isconnected())
    {
        const PSMoveProtocol::ControllerDataFrame_PSNaviState &psnavi_data_frame= data_frame->psnavi_state();

        unsigned int button_bitmask= data_frame->button_down_bitmask();
        update_button_state(L1Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L1);
        update_button_state(L2Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L2);
        update_button_state(L3Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L3);
        update_button_state(CircleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CIRCLE);
        update_button_state(CrossButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CROSS);
        update_button_state(PSButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_PS);
        update_button_state(TriggerButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIGGER);
        update_button_state(DPadUpButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_UP);
        update_button_state(DPadRightButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_RIGHT);
        update_button_state(DPadDownButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_DOWN);
        update_button_state(DPadLeftButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_LEFT);

        //###bwalker $TODO make sure this is in the range [0, 255]
        this->TriggerValue= static_cast<unsigned char>(psnavi_data_frame.trigger_value());
        this->Stick_XAxis= static_cast<unsigned char>(psnavi_data_frame.stick_xaxis());
        this->Stick_YAxis= static_cast<unsigned char>(psnavi_data_frame.stick_yaxis());

        this->bValid= true;
    }
    else
    {
        Clear();
    }
}

//-- ClientControllerView -----
ClientControllerView::ClientControllerView(int PSMoveID)
{
    Clear();
    this->ControllerID= PSMoveID;
}

void ClientControllerView::Clear()
{
    ControllerID = -1;
    SequenceNum= -1;
    ListenerCount= 0;

    IsConnected= false;

    ControllerViewType= None;
    memset(&ViewState, 0, sizeof(ViewState));

    data_frame_last_received_time=
        std::chrono::duration_cast< std::chrono::milliseconds >(
                std::chrono::system_clock::now().time_since_epoch()).count();
    data_frame_average_fps= 0.f;
}

void ClientControllerView::ApplyControllerDataFrame(
    const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    assert(data_frame->controller_id() == ControllerID);

    // Compute the data frame receive window statistics if we have received enough samples
    {
        long long now =
            std::chrono::duration_cast< std::chrono::milliseconds >(
                std::chrono::system_clock::now().time_since_epoch()).count();
        float seconds= static_cast<float>(now - data_frame_last_received_time) / 1000.f;
        float fps= 1.f / seconds;

        data_frame_average_fps= (0.9f)*data_frame_average_fps + (0.1f)*fps;
        data_frame_last_received_time= now;
    }

    if (data_frame->sequence_num() > this->SequenceNum)
    {
        this->SequenceNum= data_frame->sequence_num();
        this->IsConnected= data_frame->isconnected();

        switch(data_frame->controller_type())
        {
            case PSMoveProtocol::ControllerDataFrame_ControllerType_PSMOVE:
            {
                this->ControllerViewType= PSMove;
                this->ViewState.PSMoveView.ApplyControllerDataFrame(data_frame);
            } break;

            case PSMoveProtocol::ControllerDataFrame_ControllerType_PSNAVI:
            {
                this->ControllerViewType= PSNavi;
                this->ViewState.PSNaviView.ApplyControllerDataFrame(data_frame);
            } break;

            default:
                assert(0 && "Unhandled controller type");
        }
    }
}

//-- helper functions -----
static void update_button_state(
    PSMoveButtonState &button,
    unsigned int button_bitmask,
    unsigned int button_bit)
{
    const bool is_down= (button_bitmask & (1 << button_bit)) > 0;

    switch (button)
    {
    case PSMoveButton_UP:
        button= is_down ? PSMoveButton_PRESSED : PSMoveButton_UP;
        break;
    case PSMoveButton_PRESSED:
        button= is_down ? PSMoveButton_DOWN : PSMoveButton_RELEASED;
        break;
    case PSMoveButton_DOWN:
        button= is_down ? PSMoveButton_DOWN : PSMoveButton_RELEASED;
        break;
    case PSMoveButton_RELEASED:
        button= is_down ? PSMoveButton_PRESSED : PSMoveButton_UP;
        break;
    };
}<commit_msg>Fixed uncaught divide by zero case in client controller view update fps calculation.<commit_after>//-- includes -----
#include "ClientControllerView.h"
#include "PSMoveProtocol.pb.h"
#include <chrono>
#include <assert.h>

//-- pre-declarations -----

//-- constants -----
const PSMoveVector3 g_psmove_vector3_zero= {0.f, 0.f, 0.f};
const PSMoveVector3 *k_psmove_vector3_zero= &g_psmove_vector3_zero;

const PSMoveQuaternion g_psmove_quaternion_identity= {1.f, 0.f, 0.f, 0.f};
const PSMoveQuaternion *k_psmove_quaternion_identity= &g_psmove_quaternion_identity;

//-- prototypes ----
static void update_button_state(PSMoveButtonState &button, unsigned int button_bitmask, unsigned int button_bit);

//-- implementation -----

//-- ClientPSMoveView -----
void ClientPSMoveView::Clear()
{
    bValid= false;
    bIsTrackingEnabled= false;
    bIsCurrentlyTracking= false;

    Pose.Clear();

    TriangleButton= PSMoveButton_UP;
    CircleButton= PSMoveButton_UP;
    CrossButton= PSMoveButton_UP;
    SquareButton= PSMoveButton_UP;
    SelectButton= PSMoveButton_UP;
    StartButton= PSMoveButton_UP;
    PSButton= PSMoveButton_UP;
    MoveButton= PSMoveButton_UP;
    TriggerButton= PSMoveButton_UP;

    TriggerValue= 0;
}

void ClientPSMoveView::ApplyControllerDataFrame(const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    if (data_frame->isconnected())
    {
        const PSMoveProtocol::ControllerDataFrame_PSMoveState &psmove_data_frame= data_frame->psmove_state();

        this->bIsTrackingEnabled= psmove_data_frame.istrackingenabled();
        this->bIsCurrentlyTracking= psmove_data_frame.iscurrentlytracking();

        this->Pose.Orientation.w= psmove_data_frame.orientation().w();
        this->Pose.Orientation.x= psmove_data_frame.orientation().x();
        this->Pose.Orientation.y= psmove_data_frame.orientation().y();
        this->Pose.Orientation.z= psmove_data_frame.orientation().z();

        this->Pose.Position.x= psmove_data_frame.position().x();
        this->Pose.Position.y= psmove_data_frame.position().y();
        this->Pose.Position.z= psmove_data_frame.position().z();

        unsigned int button_bitmask= data_frame->button_down_bitmask();
        update_button_state(TriangleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIANGLE);
        update_button_state(CircleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CIRCLE);
        update_button_state(CrossButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CROSS);
        update_button_state(SquareButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_SQUARE);
        update_button_state(SelectButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_SELECT);
        update_button_state(StartButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_START);
        update_button_state(PSButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_PS);
        update_button_state(MoveButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_MOVE);
        update_button_state(TriggerButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIGGER);

        //###bwalker $TODO make sure this is in the range [0, 255]
        this->TriggerValue= static_cast<unsigned char>(psmove_data_frame.trigger_value());

        this->bValid= true;
    }
    else
    {
        Clear();
    }
}

//-- ClientPSNaviView -----
void ClientPSNaviView::Clear()
{
    bValid= false;

    L1Button= PSMoveButton_UP;
    L2Button= PSMoveButton_UP;
    L3Button= PSMoveButton_UP;
    CircleButton= PSMoveButton_UP;
    CrossButton= PSMoveButton_UP;
    PSButton= PSMoveButton_UP;
    TriggerButton= PSMoveButton_UP;
    DPadUpButton= PSMoveButton_UP;
    DPadRightButton= PSMoveButton_UP;
    DPadDownButton= PSMoveButton_UP;
    DPadLeftButton= PSMoveButton_UP;

    TriggerValue= 0;
    Stick_XAxis= 0x80;
    Stick_YAxis= 0x80;
}

void ClientPSNaviView::ApplyControllerDataFrame(const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    if (data_frame->isconnected())
    {
        const PSMoveProtocol::ControllerDataFrame_PSNaviState &psnavi_data_frame= data_frame->psnavi_state();

        unsigned int button_bitmask= data_frame->button_down_bitmask();
        update_button_state(L1Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L1);
        update_button_state(L2Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L2);
        update_button_state(L3Button, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_L3);
        update_button_state(CircleButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CIRCLE);
        update_button_state(CrossButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_CROSS);
        update_button_state(PSButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_PS);
        update_button_state(TriggerButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_TRIGGER);
        update_button_state(DPadUpButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_UP);
        update_button_state(DPadRightButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_RIGHT);
        update_button_state(DPadDownButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_DOWN);
        update_button_state(DPadLeftButton, button_bitmask, PSMoveProtocol::ControllerDataFrame_ButtonType_LEFT);

        //###bwalker $TODO make sure this is in the range [0, 255]
        this->TriggerValue= static_cast<unsigned char>(psnavi_data_frame.trigger_value());
        this->Stick_XAxis= static_cast<unsigned char>(psnavi_data_frame.stick_xaxis());
        this->Stick_YAxis= static_cast<unsigned char>(psnavi_data_frame.stick_yaxis());

        this->bValid= true;
    }
    else
    {
        Clear();
    }
}

//-- ClientControllerView -----
ClientControllerView::ClientControllerView(int PSMoveID)
{
    Clear();
    this->ControllerID= PSMoveID;
}

void ClientControllerView::Clear()
{
    ControllerID = -1;
    SequenceNum= -1;
    ListenerCount= 0;

    IsConnected= false;

    ControllerViewType= None;
    memset(&ViewState, 0, sizeof(ViewState));

    data_frame_last_received_time=
        std::chrono::duration_cast< std::chrono::milliseconds >(
                std::chrono::system_clock::now().time_since_epoch()).count();
    data_frame_average_fps= 0.f;
}

void ClientControllerView::ApplyControllerDataFrame(
    const PSMoveProtocol::ControllerDataFrame *data_frame)
{
    assert(data_frame->controller_id() == ControllerID);

    // Compute the data frame receive window statistics if we have received enough samples
    {
        long long now =
            std::chrono::duration_cast< std::chrono::milliseconds >(
                std::chrono::system_clock::now().time_since_epoch()).count();
        long long diff= now - data_frame_last_received_time;

        if (diff > 0)
        {
            float seconds= static_cast<float>(diff) / 1000.f;
            float fps= 1.f / seconds;

            data_frame_average_fps= (0.9f)*data_frame_average_fps + (0.1f)*fps;
        }

        data_frame_last_received_time= now;
    }

    if (data_frame->sequence_num() > this->SequenceNum)
    {
        this->SequenceNum= data_frame->sequence_num();
        this->IsConnected= data_frame->isconnected();

        switch(data_frame->controller_type())
        {
            case PSMoveProtocol::ControllerDataFrame_ControllerType_PSMOVE:
            {
                this->ControllerViewType= PSMove;
                this->ViewState.PSMoveView.ApplyControllerDataFrame(data_frame);
            } break;

            case PSMoveProtocol::ControllerDataFrame_ControllerType_PSNAVI:
            {
                this->ControllerViewType= PSNavi;
                this->ViewState.PSNaviView.ApplyControllerDataFrame(data_frame);
            } break;

            default:
                assert(0 && "Unhandled controller type");
        }
    }
}

//-- helper functions -----
static void update_button_state(
    PSMoveButtonState &button,
    unsigned int button_bitmask,
    unsigned int button_bit)
{
    const bool is_down= (button_bitmask & (1 << button_bit)) > 0;

    switch (button)
    {
    case PSMoveButton_UP:
        button= is_down ? PSMoveButton_PRESSED : PSMoveButton_UP;
        break;
    case PSMoveButton_PRESSED:
        button= is_down ? PSMoveButton_DOWN : PSMoveButton_RELEASED;
        break;
    case PSMoveButton_DOWN:
        button= is_down ? PSMoveButton_DOWN : PSMoveButton_RELEASED;
        break;
    case PSMoveButton_RELEASED:
        button= is_down ? PSMoveButton_PRESSED : PSMoveButton_UP;
        break;
    };
}<|endoftext|>


<commit_before>#include "command.h"
#include "../CommandHandler.h"
#include "../OptionParser.h"
#include "../version.h"

/* full name of the command */
CMDNAME("about");
/* description of the command */
CMDDESCR("print bot information");
/* command usage synopsis */
CMDUSAGE("$about");

/* about: print bot information */
std::string CommandHandler::about(struct cmdinfo *c)
{
	int opt;
	OptionParser op(c->fullCmd, "");
	static struct OptionParser::option long_opts[] = {
		{ "help", NO_ARG, 'h' },
		{ 0, 0, 0 }
	};

	while ((opt = op.getopt_long(long_opts)) != EOF) {
		switch (opt) {
		case 'h':
			return HELPMSG(CMDNAME, CMDUSAGE, CMDDESCR);
		case '?':
			return std::string(op.opterr());
		default:
			return "";
		}
	}

	return "[ABOUT] " + m_name + " is running " + std::string(BOT_NAME)
		+ " " + std::string(BOT_VERSION) + ". Find out more at "
		+ std::string(BOT_WEBSITE);
}
<commit_msg>Add source option to about<commit_after>#include "command.h"
#include "../CommandHandler.h"
#include "../OptionParser.h"
#include "../version.h"

/* full name of the command */
CMDNAME("about");
/* description of the command */
CMDDESCR("print bot information");
/* command usage synopsis */
CMDUSAGE("$about [-s]");

/* about: print bot information */
std::string CommandHandler::about(struct cmdinfo *c)
{
	int opt;
	OptionParser op(c->fullCmd, "s");
	static struct OptionParser::option long_opts[] = {
		{ "help", NO_ARG, 'h' },
		{ "source", NO_ARG, 's' },
		{ 0, 0, 0 }
	};

	while ((opt = op.getopt_long(long_opts)) != EOF) {
		switch (opt) {
		case 'h':
			return HELPMSG(CMDNAME, CMDUSAGE, CMDDESCR);
		case 's':
			return "[ABOUT] source: " + SOURCE;
		case '?':
			return std::string(op.opterr());
		default:
			return "";
		}
	}

	return "[ABOUT] " + m_name + " is running " + std::string(BOT_NAME)
		+ " " + std::string(BOT_VERSION) + ". Find out more at "
		+ std::string(BOT_WEBSITE);
}
<|endoftext|>


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

#include "shell/browser/extensions/api/resources_private/resources_private_api.h"

#include <memory>
#include <string>
#include <utility>

#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/extensions/api/resources_private.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/zoom/page_zoom_constants.h"
#include "pdf/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"

#if BUILDFLAG(ENABLE_PDF)
#include "pdf/pdf_features.h"
#endif  // BUILDFLAG(ENABLE_PDF)

// To add a new component to this API, simply:
// 1. Add your component to the Component enum in
//      chrome/common/extensions/api/resources_private.idl
// 2. Create an AddStringsForMyComponent(base::DictionaryValue * dict) method.
// 3. Tie in that method to the switch statement in Run()

namespace extensions {

namespace {

void AddStringsForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
  static constexpr webui::LocalizedString kPdfResources[] = {
      {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
      {"passwordPrompt", IDS_PDF_NEED_PASSWORD},
      {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
      {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
      {"pageLoading", IDS_PDF_PAGE_LOADING},
      {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
      {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
      {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
      {"bookmarks", IDS_PDF_BOOKMARKS},
      {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
      {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
      {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
      {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
      {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
      {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
      {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
      {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
  };
  for (const auto& resource : kPdfResources)
    dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));

  dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
#endif  // BUILDFLAG(ENABLE_PDF)
}

void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
  dict->SetKey("pdfFormSaveEnabled",
               base::Value(base::FeatureList::IsEnabled(
                   chrome_pdf::features::kSaveEditedPDFForm)));
  dict->SetKey("pdfAnnotationsEnabled",
               base::Value(base::FeatureList::IsEnabled(
                   chrome_pdf::features::kPDFAnnotations)));

  // TODO(nornagon): enable printing once it works.
  bool enable_printing = false;
  dict->SetKey("printingEnabled", base::Value(enable_printing));
#endif  // BUILDFLAG(ENABLE_PDF)
}

}  // namespace

namespace get_strings = api::resources_private::GetStrings;

ResourcesPrivateGetStringsFunction::ResourcesPrivateGetStringsFunction() {}

ResourcesPrivateGetStringsFunction::~ResourcesPrivateGetStringsFunction() {}

ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
  std::unique_ptr<get_strings::Params> params(
      get_strings::Params::Create(*args_));
  auto dict = std::make_unique<base::DictionaryValue>();

  api::resources_private::Component component = params->component;

  switch (component) {
    case api::resources_private::COMPONENT_PDF:
      AddStringsForPdf(dict.get());
      AddAdditionalDataForPdf(dict.get());
      break;
    case api::resources_private::COMPONENT_IDENTITY:
      NOTREACHED();
      break;
    case api::resources_private::COMPONENT_NONE:
      NOTREACHED();
      break;
  }

  const std::string& app_locale = g_browser_process->GetApplicationLocale();
  webui::SetLoadTimeDataDefaults(app_locale, dict.get());

  return RespondNow(OneArgument(std::move(dict)));
}

}  // namespace extensions
<commit_msg>fix: add missing pdfTwoUpViewEnabled status (#22735)<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shell/browser/extensions/api/resources_private/resources_private_api.h"

#include <memory>
#include <string>
#include <utility>

#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/extensions/api/resources_private.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/zoom/page_zoom_constants.h"
#include "pdf/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"

#if BUILDFLAG(ENABLE_PDF)
#include "pdf/pdf_features.h"
#endif  // BUILDFLAG(ENABLE_PDF)

// To add a new component to this API, simply:
// 1. Add your component to the Component enum in
//      chrome/common/extensions/api/resources_private.idl
// 2. Create an AddStringsForMyComponent(base::DictionaryValue * dict) method.
// 3. Tie in that method to the switch statement in Run()

namespace extensions {

namespace {

void AddStringsForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
  static constexpr webui::LocalizedString kPdfResources[] = {
      {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
      {"passwordPrompt", IDS_PDF_NEED_PASSWORD},
      {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
      {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
      {"pageLoading", IDS_PDF_PAGE_LOADING},
      {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
      {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
      {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
      {"bookmarks", IDS_PDF_BOOKMARKS},
      {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
      {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
      {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
      {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
      {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
      {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
      {"tooltipTwoUpViewDisable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_DISABLE},
      {"tooltipTwoUpViewEnable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_ENABLE},
      {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
      {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
  };
  for (const auto& resource : kPdfResources)
    dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));

  dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
#endif  // BUILDFLAG(ENABLE_PDF)
}

void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
  dict->SetKey("pdfFormSaveEnabled",
               base::Value(base::FeatureList::IsEnabled(
                   chrome_pdf::features::kSaveEditedPDFForm)));
  dict->SetKey("pdfAnnotationsEnabled",
               base::Value(base::FeatureList::IsEnabled(
                   chrome_pdf::features::kPDFAnnotations)));
  dict->SetKey("pdfTwoUpViewEnabled",
               base::Value(base::FeatureList::IsEnabled(
                   chrome_pdf::features::kPDFTwoUpView)));

  // TODO(nornagon): enable printing once it works.
  bool enable_printing = false;
  dict->SetKey("printingEnabled", base::Value(enable_printing));
#endif  // BUILDFLAG(ENABLE_PDF)
}

}  // namespace

namespace get_strings = api::resources_private::GetStrings;

ResourcesPrivateGetStringsFunction::ResourcesPrivateGetStringsFunction() {}

ResourcesPrivateGetStringsFunction::~ResourcesPrivateGetStringsFunction() {}

ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
  std::unique_ptr<get_strings::Params> params(
      get_strings::Params::Create(*args_));
  auto dict = std::make_unique<base::DictionaryValue>();

  api::resources_private::Component component = params->component;

  switch (component) {
    case api::resources_private::COMPONENT_PDF:
      AddStringsForPdf(dict.get());
      AddAdditionalDataForPdf(dict.get());
      break;
    case api::resources_private::COMPONENT_IDENTITY:
      NOTREACHED();
      break;
    case api::resources_private::COMPONENT_NONE:
      NOTREACHED();
      break;
  }

  const std::string& app_locale = g_browser_process->GetApplicationLocale();
  webui::SetLoadTimeDataDefaults(app_locale, dict.get());

  return RespondNow(OneArgument(std::move(dict)));
}

}  // namespace extensions
<|endoftext|>


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

#include "shader.h"
#include "pipeline.h"
#include "compiler/shader/compiler_interface.h"
#include "compiler/pipeline/pipeline_compiler_interface.h"
#include "compiler/pipeline/brw_context.h"
#include "compiler/pipeline/brw_shader.h"
#include "compiler/mesa-utils/src/mesa/main/context.h"
#include "compiler/mesa-utils/src/glsl/ralloc.h"
#include "compiler/pipeline/brw_device_info.h"
#include "compiler/pipeline/brw_wm.h"

void initialize_brw_context(struct brw_context *brw)
{

    // create a stripped down context for compilation
    initialize_mesa_context_to_defaults(&brw->ctx);

    //
    // init the things pulled from DRI in brwCreateContext
    //
    struct brw_device_info *devInfo = rzalloc(brw, struct brw_device_info);
    devInfo->gen = 7;
    devInfo->gt = 3;
    devInfo->is_g4x = false;
    devInfo->is_baytrail = false;
    devInfo->is_haswell = true;
    devInfo->has_llc = true;
    devInfo->has_pln = true;
    devInfo->has_compr4 = true;
    devInfo->has_negative_rhw_bug = false;
    devInfo->needs_unlit_centroid_workaround = true;

    // hand code values until we have something to pull from
    // use brw_device_info_hsw_gt3
    brw->intelScreen = rzalloc(brw, struct intel_screen);
    brw->intelScreen->devinfo = devInfo;

    brw->gen = brw->intelScreen->devinfo->gen;
    brw->gt = brw->intelScreen->devinfo->gt;
    brw->is_g4x = brw->intelScreen->devinfo->is_g4x;
    brw->is_baytrail = brw->intelScreen->devinfo->is_baytrail;
    brw->is_haswell = brw->intelScreen->devinfo->is_haswell;
    brw->has_llc = brw->intelScreen->devinfo->has_llc;
    brw->has_pln = brw->intelScreen->devinfo->has_pln;
    brw->has_compr4 = brw->intelScreen->devinfo->has_compr4;
    brw->has_negative_rhw_bug = brw->intelScreen->devinfo->has_negative_rhw_bug;
    brw->needs_unlit_centroid_workaround =
       brw->intelScreen->devinfo->needs_unlit_centroid_workaround;

    brw->vs.base.stage = MESA_SHADER_VERTEX;
    brw->gs.base.stage = MESA_SHADER_GEOMETRY;
    brw->wm.base.stage = MESA_SHADER_FRAGMENT;

    //
    // init what remains of intel_screen
    //
    brw->intelScreen->deviceID = 0;
    brw->intelScreen->program_id = 0;

    brw_fs_alloc_reg_sets(brw->intelScreen);
    brw_vec4_alloc_reg_set(brw->intelScreen);

    brw->shader_prog = brw_new_shader_program(&brw->ctx, 0);
}

static inline void pipeline_destroy_compile(struct brw_context *brw) {
    ralloc_free(brw->shader_prog);
    ralloc_free(brw);
}

static void hexdump(FILE *fp, void *ptr, int buflen) {
  unsigned int *buf = (unsigned int*)ptr;
  int i, j;
  for (i=0; i<(buflen/4); i+=4) {
    fprintf(fp,"%06x: ", i);
    for (j=0; j<4; j++)
      if (i+j < (buflen/4))
        fprintf(fp,"%08x ", buf[i+j]);
      else
        fprintf(fp,"   ");
    fprintf(fp,"\n");
  }

  fflush(fp);
}

static void fs_data_dump(FILE *fp, struct brw_wm_prog_data* data)
{
    fprintf(fp, "\n=== begin brw_wm_prog_data ===\n");

    fprintf(fp, "data->base.binding_table.size_bytes = %u\n",
                 data->base.binding_table.size_bytes);
    fprintf(fp, "data->base.binding_table.pull_constants_start = %u\n",
                 data->base.binding_table.pull_constants_start);
    fprintf(fp, "data->base.binding_table.texture_start = %u\n",
                 data->base.binding_table.texture_start);
    fprintf(fp, "data->base.binding_table.gather_texture_start = %u\n",
                 data->base.binding_table.gather_texture_start);
    fprintf(fp, "data->base.binding_table.ubo_start = %u\n",
                 data->base.binding_table.ubo_start);
    fprintf(fp, "data->base.binding_table.abo_start = %u\n",
                 data->base.binding_table.abo_start);
    fprintf(fp, "data->base.binding_table.shader_time_start = %u\n",
                 data->base.binding_table.shader_time_start);

    fprintf(fp, "data->base.nr_params = %u\n",
                 data->base.nr_params);
    fprintf(fp, "data->base.nr_pull_params = %u\n",
                 data->base.nr_pull_params);

    // invalid pointers
    //data->base.param;
    //data->base.pull_param;

    fprintf(fp, "data->curb_read_length = %u\n",
                 data->curb_read_length);
    fprintf(fp, "data->num_varying_inputs = %u\n",
                 data->num_varying_inputs);

    fprintf(fp, "data->first_curbe_grf = %u\n",
                 data->first_curbe_grf);
    fprintf(fp, "data->first_curbe_grf_16 = %u\n",
                 data->first_curbe_grf_16);
    fprintf(fp, "data->reg_blocks = %u\n",
                 data->reg_blocks);
    fprintf(fp, "data->reg_blocks_16 = %u\n",
                 data->reg_blocks_16);
    fprintf(fp, "data->total_scratch = %u\n",
                 data->total_scratch);
    fprintf(fp, "data->binding_table.render_target_start = %u\n",
                 data->binding_table.render_target_start);

    fprintf(fp, "data->dual_src_blend = %s\n",
                 data->dual_src_blend ? "true" : "false");
    fprintf(fp, "data->uses_pos_offset = %s\n",
                 data->uses_pos_offset ? "true" : "false");
    fprintf(fp, "data->uses_omask = %s\n",
                 data->uses_omask ? "true" : "false");
    fprintf(fp, "data->prog_offset_16 = %u\n",
                 data->prog_offset_16);

    fprintf(fp, "data->barycentric_interp_modes = %u\n",
                 data->barycentric_interp_modes);

    for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
        fprintf(fp, "data->urb_setup[%i] = %i\n",
                  i, data->urb_setup[i]);
    }

    fprintf(fp, "=== end brw_wm_prog_data ===\n");

    fflush(fp);
}

extern "C" {

// invoke backend compiler to generate ISA and supporting data structures
XGL_RESULT intel_pipeline_shader_compile(struct intel_pipeline_shader *pipe_shader,
                                         const struct intel_shader *shader)
{
    XGL_RESULT status = XGL_SUCCESS;

    // create a brw_context
    struct brw_context *brw = rzalloc(NULL, struct brw_context);

    // allocate sub structures on the stack
    initialize_brw_context(brw);

    // LunarG : TODO - should this have been set for us somewhere?
    shader->ir->shader_program->Type =
            shader->ir->shader_program->Shaders[0]->Stage;

    if (brw_link_shader(&brw->ctx, shader->ir->shader_program)) {

        // first take at standalone backend compile
        switch(shader->ir->shader_program->Shaders[0]->Type) {
        case GL_VERTEX_SHADER:
        {
            pipe_shader->codeSize = get_vs_program_size(brw->shader_prog);

            pipe_shader->pCode = icd_alloc(pipe_shader->codeSize, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
            if (!pipe_shader->pCode) {
                status = XGL_ERROR_OUT_OF_MEMORY;
                break;
            }

            // copy the ISA out of our compile context, it is about to poof away
            memcpy(pipe_shader->pCode, get_vs_program(brw->shader_prog), pipe_shader->codeSize);

            struct brw_vs_prog_data *data = get_vs_prog_data(brw->shader_prog);

            if (data->uses_vertexid)
                pipe_shader->uses |= INTEL_SHADER_USE_VID;

            // These are really best guesses, and will require more work to
            // understand as we turn on more features
            pipe_shader->in_count = data->base.urb_read_length;// = 1;
            pipe_shader->out_count = data->base.vue_map.num_slots;// = 2;
            pipe_shader->urb_grf_start = data->base.dispatch_grf_start_reg;// = 1;

            // The following continue to match what is baked in to test case
            pipe_shader->sampler_count = shader->sampler_count;
            pipe_shader->barycentric_interps = shader->barycentric_interps;

            fprintf(stdout,"\nISA generated by compiler:\n");
            fprintf(stdout,"ISA size: %i\n", pipe_shader->codeSize);
            hexdump(stdout, pipe_shader->pCode, pipe_shader->codeSize);
            fflush(stdout);
        }
            break;

        case GL_FRAGMENT_SHADER:
        {
            // Start pulling bits out of our compile result.
            // see upload_ps_state() for references about what I believe each of these values are

            // I would prefer to find a way to pull this data out without exposing
            // the internals of the compiler, but it hasn't presented itself yet

            pipe_shader->codeSize = get_wm_program_size(brw->shader_prog);

            pipe_shader->pCode = icd_alloc(pipe_shader->codeSize, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
            if (!pipe_shader->pCode) {
                status = XGL_ERROR_OUT_OF_MEMORY;
                break;
            }

            // copy the ISA out of our compile context, it is about to poof away
            memcpy(pipe_shader->pCode, get_wm_program(brw->shader_prog), pipe_shader->codeSize);

            struct brw_wm_prog_data *data = get_wm_prog_data(brw->shader_prog);

            // print out the supporting structures generated by the BE compile:
            fs_data_dump(stdout, data);

            pipe_shader->surface_count = data->base.binding_table.size_bytes / 4;
            pipe_shader->urb_grf_start = data->first_curbe_grf;
            pipe_shader->in_count      = data->num_varying_inputs;

            // Ensure this is 1:1, or create a converter
            pipe_shader->barycentric_interps = data->barycentric_interp_modes;

            // The following continue to match what is baked in to test case
            pipe_shader->uses = shader->uses;
            pipe_shader->out_count = shader->out_count;
            pipe_shader->sampler_count = shader->sampler_count;

            fprintf(stdout,"\nISA generated by compiler:\n");
            fprintf(stdout,"ISA size: %i\n", pipe_shader->codeSize);
            hexdump(stdout, pipe_shader->pCode, pipe_shader->codeSize);
            fflush(stdout);
        }
            break;

        case GL_GEOMETRY_SHADER:
        case GL_COMPUTE_SHADER:
        default:
            assert(0);
            status = XGL_ERROR_BAD_PIPELINE_DATA;
        }
    } else {
        assert(0);
        status = XGL_ERROR_BAD_PIPELINE_DATA;
    }

    pipeline_destroy_compile(brw);

    return status;
}

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

#include "shader.h"
#include "pipeline.h"
#include "compiler/shader/compiler_interface.h"
#include "compiler/pipeline/pipeline_compiler_interface.h"
#include "compiler/pipeline/brw_context.h"
#include "compiler/pipeline/brw_shader.h"
#include "compiler/mesa-utils/src/mesa/main/context.h"
#include "compiler/mesa-utils/src/glsl/ralloc.h"
#include "compiler/pipeline/brw_device_info.h"
#include "compiler/pipeline/brw_wm.h"

void initialize_brw_context(struct brw_context *brw)
{

    // create a stripped down context for compilation
    initialize_mesa_context_to_defaults(&brw->ctx);

    //
    // init the things pulled from DRI in brwCreateContext
    //
    struct brw_device_info *devInfo = rzalloc(brw, struct brw_device_info);
    devInfo->gen = 7;
    devInfo->gt = 3;
    devInfo->is_g4x = false;
    devInfo->is_baytrail = false;
    devInfo->is_haswell = true;
    devInfo->has_llc = true;
    devInfo->has_pln = true;
    devInfo->has_compr4 = true;
    devInfo->has_negative_rhw_bug = false;
    devInfo->needs_unlit_centroid_workaround = true;

    // hand code values until we have something to pull from
    // use brw_device_info_hsw_gt3
    brw->intelScreen = rzalloc(brw, struct intel_screen);
    brw->intelScreen->devinfo = devInfo;

    brw->gen = brw->intelScreen->devinfo->gen;
    brw->gt = brw->intelScreen->devinfo->gt;
    brw->is_g4x = brw->intelScreen->devinfo->is_g4x;
    brw->is_baytrail = brw->intelScreen->devinfo->is_baytrail;
    brw->is_haswell = brw->intelScreen->devinfo->is_haswell;
    brw->has_llc = brw->intelScreen->devinfo->has_llc;
    brw->has_pln = brw->intelScreen->devinfo->has_pln;
    brw->has_compr4 = brw->intelScreen->devinfo->has_compr4;
    brw->has_negative_rhw_bug = brw->intelScreen->devinfo->has_negative_rhw_bug;
    brw->needs_unlit_centroid_workaround =
       brw->intelScreen->devinfo->needs_unlit_centroid_workaround;

    brw->vs.base.stage = MESA_SHADER_VERTEX;
    brw->gs.base.stage = MESA_SHADER_GEOMETRY;
    brw->wm.base.stage = MESA_SHADER_FRAGMENT;

    //
    // init what remains of intel_screen
    //
    brw->intelScreen->deviceID = 0;
    brw->intelScreen->program_id = 0;

    brw_fs_alloc_reg_sets(brw->intelScreen);
    brw_vec4_alloc_reg_set(brw->intelScreen);

    brw->shader_prog = brw_new_shader_program(&brw->ctx, 0);
}

static inline void pipeline_destroy_compile(struct brw_context *brw) {
    ralloc_free(brw->shader_prog);
    ralloc_free(brw);
}

static void hexdump(FILE *fp, void *ptr, int buflen) {
  unsigned int *buf = (unsigned int*)ptr;
  int i, j;
  for (i=0; i<(buflen/4); i+=4) {
    fprintf(fp,"%06x: ", i);
    for (j=0; j<4; j++)
      if (i+j < (buflen/4))
        fprintf(fp,"%08x ", buf[i+j]);
      else
        fprintf(fp,"   ");
    fprintf(fp,"\n");
  }

  fflush(fp);
}

static void fs_data_dump(FILE *fp, struct brw_wm_prog_data* data)
{
    fprintf(fp, "\n=== begin brw_wm_prog_data ===\n");

    fprintf(fp, "data->base.binding_table.size_bytes = %u\n",
                 data->base.binding_table.size_bytes);
    fprintf(fp, "data->base.binding_table.pull_constants_start = %u\n",
                 data->base.binding_table.pull_constants_start);
    fprintf(fp, "data->base.binding_table.texture_start = %u\n",
                 data->base.binding_table.texture_start);
    fprintf(fp, "data->base.binding_table.gather_texture_start = %u\n",
                 data->base.binding_table.gather_texture_start);
    fprintf(fp, "data->base.binding_table.ubo_start = %u\n",
                 data->base.binding_table.ubo_start);
    fprintf(fp, "data->base.binding_table.abo_start = %u\n",
                 data->base.binding_table.abo_start);
    fprintf(fp, "data->base.binding_table.shader_time_start = %u\n",
                 data->base.binding_table.shader_time_start);

    fprintf(fp, "data->base.nr_params = %u\n",
                 data->base.nr_params);
    fprintf(fp, "data->base.nr_pull_params = %u\n",
                 data->base.nr_pull_params);

    fprintf(fp, "== push constants: ==\n");
    fprintf(fp, "data->base.nr_params = %u\n",
                 data->base.nr_params);

    for (int i = 0; i < data->base.nr_params; ++i) {
        fprintf(fp, "data->base.param = %p\n",
                     data->base.param);
        fprintf(fp, "*data->base.param = %p\n",
                     *data->base.param);
        fprintf(fp, "**data->base.param = %f\n",
                     **data->base.param);
    }

    fprintf(fp, "== pull constants: ==\n");
    fprintf(fp, "data->base.nr_pull_params = %u\n",
                 data->base.nr_pull_params);

    for (int i = 0; i < data->base.nr_pull_params; ++i) {
        fprintf(fp, "data->base.pull_param = %p\n",
                     data->base.pull_param);
        fprintf(fp, "*data->base.pull_param = %p\n",
                     *data->base.pull_param);
        fprintf(fp, "**data->base.pull_param = %f\n",
                     **data->base.pull_param);
    }

    fprintf(fp, "data->curb_read_length = %u\n",
                 data->curb_read_length);
    fprintf(fp, "data->num_varying_inputs = %u\n",
                 data->num_varying_inputs);

    fprintf(fp, "data->first_curbe_grf = %u\n",
                 data->first_curbe_grf);
    fprintf(fp, "data->first_curbe_grf_16 = %u\n",
                 data->first_curbe_grf_16);
    fprintf(fp, "data->reg_blocks = %u\n",
                 data->reg_blocks);
    fprintf(fp, "data->reg_blocks_16 = %u\n",
                 data->reg_blocks_16);
    fprintf(fp, "data->total_scratch = %u\n",
                 data->total_scratch);
    fprintf(fp, "data->binding_table.render_target_start = %u\n",
                 data->binding_table.render_target_start);

    fprintf(fp, "data->dual_src_blend = %s\n",
                 data->dual_src_blend ? "true" : "false");
    fprintf(fp, "data->uses_pos_offset = %s\n",
                 data->uses_pos_offset ? "true" : "false");
    fprintf(fp, "data->uses_omask = %s\n",
                 data->uses_omask ? "true" : "false");
    fprintf(fp, "data->prog_offset_16 = %u\n",
                 data->prog_offset_16);

    fprintf(fp, "data->barycentric_interp_modes = %u\n",
                 data->barycentric_interp_modes);

    for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
        fprintf(fp, "data->urb_setup[%i] = %i\n",
                  i, data->urb_setup[i]);
    }

    fprintf(fp, "=== end brw_wm_prog_data ===\n");

    fflush(fp);
}

extern "C" {

// invoke backend compiler to generate ISA and supporting data structures
XGL_RESULT intel_pipeline_shader_compile(struct intel_pipeline_shader *pipe_shader,
                                         const struct intel_shader *shader)
{
    XGL_RESULT status = XGL_SUCCESS;

    // create a brw_context
    struct brw_context *brw = rzalloc(NULL, struct brw_context);

    // allocate sub structures on the stack
    initialize_brw_context(brw);

    // LunarG : TODO - should this have been set for us somewhere?
    shader->ir->shader_program->Type =
            shader->ir->shader_program->Shaders[0]->Stage;

    if (brw_link_shader(&brw->ctx, shader->ir->shader_program)) {

        // first take at standalone backend compile
        switch(shader->ir->shader_program->Shaders[0]->Type) {
        case GL_VERTEX_SHADER:
        {
            pipe_shader->codeSize = get_vs_program_size(brw->shader_prog);

            pipe_shader->pCode = icd_alloc(pipe_shader->codeSize, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
            if (!pipe_shader->pCode) {
                status = XGL_ERROR_OUT_OF_MEMORY;
                break;
            }

            // copy the ISA out of our compile context, it is about to poof away
            memcpy(pipe_shader->pCode, get_vs_program(brw->shader_prog), pipe_shader->codeSize);

            struct brw_vs_prog_data *data = get_vs_prog_data(brw->shader_prog);

            if (data->uses_vertexid)
                pipe_shader->uses |= INTEL_SHADER_USE_VID;

            // These are really best guesses, and will require more work to
            // understand as we turn on more features
            pipe_shader->in_count = data->base.urb_read_length;// = 1;
            pipe_shader->out_count = data->base.vue_map.num_slots;// = 2;
            pipe_shader->urb_grf_start = data->base.dispatch_grf_start_reg;// = 1;

            // The following continue to match what is baked in to test case
            pipe_shader->sampler_count = shader->sampler_count;
            pipe_shader->barycentric_interps = shader->barycentric_interps;

            fprintf(stdout,"\nISA generated by compiler:\n");
            fprintf(stdout,"ISA size: %i\n", pipe_shader->codeSize);
            hexdump(stdout, pipe_shader->pCode, pipe_shader->codeSize);
            fflush(stdout);
        }
            break;

        case GL_FRAGMENT_SHADER:
        {
            // Start pulling bits out of our compile result.
            // see upload_ps_state() for references about what I believe each of these values are

            // I would prefer to find a way to pull this data out without exposing
            // the internals of the compiler, but it hasn't presented itself yet

            pipe_shader->codeSize = get_wm_program_size(brw->shader_prog);

            pipe_shader->pCode = icd_alloc(pipe_shader->codeSize, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
            if (!pipe_shader->pCode) {
                status = XGL_ERROR_OUT_OF_MEMORY;
                break;
            }

            // copy the ISA out of our compile context, it is about to poof away
            memcpy(pipe_shader->pCode, get_wm_program(brw->shader_prog), pipe_shader->codeSize);

            struct brw_wm_prog_data *data = get_wm_prog_data(brw->shader_prog);

            // print out the supporting structures generated by the BE compile:
            fs_data_dump(stdout, data);

            pipe_shader->surface_count = data->base.binding_table.size_bytes / 4;
            pipe_shader->urb_grf_start = data->first_curbe_grf;
            pipe_shader->in_count      = data->num_varying_inputs;

            // Ensure this is 1:1, or create a converter
            pipe_shader->barycentric_interps = data->barycentric_interp_modes;

            // The following continue to match what is baked in to test case
            pipe_shader->uses = shader->uses;
            pipe_shader->out_count = shader->out_count;
            pipe_shader->sampler_count = shader->sampler_count;

            fprintf(stdout,"\nISA generated by compiler:\n");
            fprintf(stdout,"ISA size: %i\n", pipe_shader->codeSize);
            hexdump(stdout, pipe_shader->pCode, pipe_shader->codeSize);
            fflush(stdout);
        }
            break;

        case GL_GEOMETRY_SHADER:
        case GL_COMPUTE_SHADER:
        default:
            assert(0);
            status = XGL_ERROR_BAD_PIPELINE_DATA;
        }
    } else {
        assert(0);
        status = XGL_ERROR_BAD_PIPELINE_DATA;
    }

    pipeline_destroy_compile(brw);

    return status;
}

} // extern "C"
<|endoftext|>


<commit_before>#pragma once

#include "RawImgDetections.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Timestamp.hpp"
#include "depthai-shared/utility/Serialization.hpp"

namespace dai {

/**
 * SpatialImgDetection structure
 *
 * Contains image detection results together with spatial location data.
 */
struct SpatialImgDetection : public ImgDetection {
    Point3f spatialCoordinates;
};

DEPTHAI_SERIALIZE_EXT(SpatialImgDetection, label, confidence, xmin, ymin, xmax, ymax, spatialCoordinates);

/// RawSpatialImgDetections structure
struct RawSpatialImgDetections : public RawBuffer {
    std::vector<SpatialImgDetection> detections;

    // Related to input ImgFrame
    int64_t sequenceNum = 0;  // increments for each frame
    Timestamp ts = {};        // generation timestamp, synced to host time
    Timestamp tsDevice = {};  // generation timestamp, direct device monotonic clock

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) const override {
        metadata = utility::serialize(*this);
        datatype = DatatypeEnum::SpatialImgDetections;
    };

    DEPTHAI_SERIALIZE(RawSpatialImgDetections, detections, sequenceNum, ts, tsDevice);
};

}  // namespace dai
<commit_msg>Expand spatial image detections with original config<commit_after>#pragma once

#include "RawImgDetections.hpp"
#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Timestamp.hpp"
#include "depthai-shared/datatype/RawSpatialLocationCalculatorConfig.hpp"
#include "depthai-shared/utility/Serialization.hpp"

namespace dai {

/**
 * SpatialImgDetection structure
 *
 * Contains image detection results together with spatial location data.
 */
struct SpatialImgDetection : public ImgDetection {
    Point3f spatialCoordinates;
    SpatialLocationCalculatorConfigData boundingBoxMapping;
};

DEPTHAI_SERIALIZE_EXT(SpatialImgDetection, label, confidence, xmin, ymin, xmax, ymax, spatialCoordinates, boundingBoxMapping);

/// RawSpatialImgDetections structure
struct RawSpatialImgDetections : public RawBuffer {
    std::vector<SpatialImgDetection> detections;

    // Related to input ImgFrame
    int64_t sequenceNum = 0;  // increments for each frame
    Timestamp ts = {};        // generation timestamp, synced to host time
    Timestamp tsDevice = {};  // generation timestamp, direct device monotonic clock

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) const override {
        metadata = utility::serialize(*this);
        datatype = DatatypeEnum::SpatialImgDetections;
    };

    DEPTHAI_SERIALIZE(RawSpatialImgDetections, detections, sequenceNum, ts, tsDevice);
};

}  // namespace dai
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2020 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/neural_layer.hpp"

namespace dll {

/*!
 * \brief Batch Normalization layer
 */
template <typename Desc>
struct batch_normalization_4d_layer_impl : neural_layer<batch_normalization_4d_layer_impl<Desc>, Desc> {
    using desc        = Desc;                                                        ///< The descriptor type
    using base_type   = neural_layer<batch_normalization_4d_layer_impl<Desc>, Desc>; ///< The base type
    using weight      = typename desc::weight;                                       ///< The data type of the layer
    using this_type   = batch_normalization_4d_layer_impl<Desc>;                     ///< The type of this layer
    using layer_t     = this_type;                                                   ///< This layer's type
    using dyn_layer_t = typename desc::dyn_layer_t;                                  ///< The dynamic version of this layer

    static constexpr size_t Kernels = desc::Kernels; ///< The number of feature maps
    static constexpr size_t W       = desc::Width;   ///< The width of feature maps
    static constexpr size_t H       = desc::Height;  ///< The height of feature maps
    static constexpr weight e        = 1e-8;          ///< Epsilon for numerical stability

    using input_one_t  = etl::fast_dyn_matrix<weight, Kernels, W, H>; ///< The type of one input
    using output_one_t = etl::fast_dyn_matrix<weight, Kernels, W, H>; ///< The type of one output
    using input_t      = std::vector<input_one_t>;                    ///< The type of the input
    using output_t     = std::vector<output_one_t>;                   ///< The type of the output

    etl::fast_matrix<weight, Kernels> gamma;
    etl::fast_matrix<weight, Kernels> beta;

    etl::fast_matrix<weight, Kernels> mean;
    etl::fast_matrix<weight, Kernels> var;

    etl::fast_matrix<weight, Kernels> last_mean;
    etl::fast_matrix<weight, Kernels> last_var;
    etl::fast_matrix<weight, Kernels> inv_var;

    etl::dyn_matrix<weight, 4> input_pre; /// B x K x W x H

    weight momentum = 0.9;

    //Backup gamma and beta
    std::unique_ptr<etl::fast_matrix<weight, Kernels>> bak_gamma; ///< Backup gamma
    std::unique_ptr<etl::fast_matrix<weight, Kernels>> bak_beta;  ///< Backup beta

    batch_normalization_4d_layer_impl() : base_type() {
        gamma = 1.0;
        beta = 0.0;
    }

    /*!
     * \brief Returns a string representation of the layer
     */
    static std::string to_short_string([[maybe_unused]] std::string pre = "") {
        return "batch_norm";
    }

    /*!
     * \brief Returns a string representation of the layer
     */
    static std::string to_full_string([[maybe_unused]] std::string pre = "") {
        return "batch_norm";
    }

    /*!
     * \brief Return the number of trainable parameters of this network.
     * \return The the number of trainable parameters of this network.
     */
    static constexpr size_t parameters() noexcept {
        return 4 * Kernels;
    }

    /*!
     * \brief Return the size of the input of this layer
     * \return The size of the input of this layer
     */
    static constexpr size_t input_size() noexcept {
        return Kernels * W * H;
    }

    /*!
     * \brief Return the size of the output of this layer
     * \return The size of the output of this layer
     */
    static constexpr size_t output_size() noexcept {
        return Kernels * W * H;
    }

    /*!
     * \brief Returns the output shape
     * \return an std::string containing the description of the output shape
     */
    std::vector<size_t> output_shape([[maybe_unused]] const std::vector<size_t>& input_shape) const {
        return {Kernels, W, H};
    }

    using base_type::test_forward_batch;
    using base_type::train_forward_batch;

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void forward_batch(Output& output, const Input& input) const {
        test_forward_batch(output, input);
    }

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void test_forward_batch(Output& output, const Input& input) const {
        const auto B = etl::dim<0>(input);

        auto inv_var = etl::force_temporary(1.0 / etl::sqrt(var + e));

        for (size_t b = 0; b < B; ++b) {
            for (size_t k = 0; k < Kernels; ++k) {
                output(b)(k) = (gamma(k) >> ((input(b)(k) - mean(k)) >> inv_var(k))) + beta(k);
            }
        }
    }

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void train_forward_batch(Output& output, const Input& input) {
        const auto B = etl::dim<0>(input);
        const auto S = B * W * H;

        // Compute the mean of the mini-batch
        last_mean = etl::bias_batch_mean_4d(input);

        // Compute the variance of the mini-batch
        last_var  = 0;

        for (size_t b = 0; b < B; ++b) {
            for (size_t k = 0; k < Kernels; ++k) {
                last_var(k) += etl::sum((input(b)(k) - last_mean(k)) >> (input(b)(k) - last_mean(k)));
            }
        }

        last_var /= S;

        inv_var  = 1.0 / etl::sqrt(last_var + e);

        input_pre.inherit_if_null(input);

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                input_pre(b)(k) = (input(b)(k) - last_mean(k)) >> inv_var(k);
                output(b)(k)    = (gamma(k) >> input_pre(b)(k)) + beta(k);
            }
        }

        //// Update the current mean and variance
        mean = momentum * mean + (1.0 - momentum) * last_mean;
        var  = momentum * var + (1.0 - momentum) * (S / (S - 1) * last_var);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template <typename C>
    void adapt_errors([[maybe_unused]] C& context) const {}

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename HH, typename C>
    void backward_batch(HH&& output, C& context) const {
        const auto B = etl::dim<0>(context.input);
        const auto S = B * W * H;

        auto dxhat = etl::force_temporary_dim_only(context.errors);

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                dxhat(b)(k) = context.errors(b)(k) >> gamma(k);
            }
        }

        auto dxhat_l      = etl::bias_batch_sum_4d(dxhat);
        auto dxhat_xhat_l = etl::bias_batch_sum_4d(dxhat >> input_pre);

        *dxhat_l;
        *dxhat_xhat_l;

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                output(b)(k) = ((1.0 / S) * inv_var(k)) >> (S * dxhat(b)(k) - dxhat_l(k) - (input_pre(b)(k) >> dxhat_xhat_l(k)));
            }
        }
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        // Gradients of gamma
        std::get<0>(context.up.context)->grad = etl::bias_batch_sum_4d(input_pre >> context.errors);

        // Gradients of beta
        std::get<1>(context.up.context)->grad = etl::bias_batch_sum_4d(context.errors);
    }

    /*!
     * \brief Prepare one empty output for this layer
     * \return an empty ETL matrix suitable to store one output of this layer
     *
     * \tparam Input The type of one Input
     */
    template <typename InputType>
    output_one_t prepare_one_output() const {
        return {};
    }

    /*!
     * \brief Prepare a set of empty outputs for this layer
     * \param samples The number of samples to prepare the output for
     * \return a container containing empty ETL matrices suitable to store samples output of this layer
     * \tparam Input The type of one input
     */
    template <typename InputType>
    static output_t prepare_output(size_t samples) {
        return output_t{samples};
    }

    /*!
     * \brief Initialize the dynamic version of the layer from the fast version of the layer
     * \param dyn Reference to the dynamic version of the layer that needs to be initialized
     */
    template<typename DLayer>
    static void dyn_init(DLayer& dyn){
        dyn.init_layer(Kernels, W, H);
    }

    /*!
     * \brief Returns the trainable variables of this layer.
     * \return a tuple containing references to the variables of this layer
     */
    decltype(auto) trainable_parameters(){
        return std::make_tuple(std::ref(gamma), std::ref(beta));
    }

    /*!
     * \brief Returns the trainable variables of this layer.
     * \return a tuple containing references to the variables of this layer
     */
    decltype(auto) trainable_parameters() const {
        return std::make_tuple(std::cref(gamma), std::cref(beta));
    }

    /*!
     * \brief Backup the weights in the secondary weights matrix
     */
    void backup_weights() {
        unique_safe_get(bak_gamma) = gamma;
        unique_safe_get(bak_beta)  = beta;
    }

    /*!
     * \brief Restore the weights from the secondary weights matrix
     */
    void restore_weights() {
        gamma = *bak_gamma;
        beta  = *bak_beta;
    }
};

// Declare the traits for the layer

template<typename Desc>
struct layer_base_traits<batch_normalization_4d_layer_impl<Desc>> {
    static constexpr bool is_neural     = true; ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false; ///< Indicates if the layer is dense
    static constexpr bool is_conv       = false; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = false; ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false; ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false;  ///< Indicates if the layer is a transform layer
    static constexpr bool is_recurrent  = false; ///< Indicates if the layer is a recurrent layer
    static constexpr bool is_multi      = false; ///< Indicates if the layer is a multi-layer layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief Specialization of sgd_context for batch_normalization_4d_layer_impl
 */
template <typename DBN, typename Desc, size_t L>
struct sgd_context<DBN, batch_normalization_4d_layer_impl<Desc>, L> {
    using layer_t = batch_normalization_4d_layer_impl<Desc>; ///< The current layer type
    using weight  = typename layer_t::weight;           ///< The data type for this layer

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> input;  ///< A batch of input
    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> output; ///< A batch of output
    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> errors; ///< A batch of errors

    sgd_context(const layer_t& /*layer*/){}
};

} //end of dll namespace
<commit_msg>Add missing timers<commit_after>//=======================================================================
// Copyright (c) 2014-2020 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/neural_layer.hpp"

namespace dll {

/*!
 * \brief Batch Normalization layer
 */
template <typename Desc>
struct batch_normalization_4d_layer_impl : neural_layer<batch_normalization_4d_layer_impl<Desc>, Desc> {
    using desc        = Desc;                                                        ///< The descriptor type
    using base_type   = neural_layer<batch_normalization_4d_layer_impl<Desc>, Desc>; ///< The base type
    using weight      = typename desc::weight;                                       ///< The data type of the layer
    using this_type   = batch_normalization_4d_layer_impl<Desc>;                     ///< The type of this layer
    using layer_t     = this_type;                                                   ///< This layer's type
    using dyn_layer_t = typename desc::dyn_layer_t;                                  ///< The dynamic version of this layer

    static constexpr size_t Kernels = desc::Kernels; ///< The number of feature maps
    static constexpr size_t W       = desc::Width;   ///< The width of feature maps
    static constexpr size_t H       = desc::Height;  ///< The height of feature maps
    static constexpr weight e        = 1e-8;          ///< Epsilon for numerical stability

    using input_one_t  = etl::fast_dyn_matrix<weight, Kernels, W, H>; ///< The type of one input
    using output_one_t = etl::fast_dyn_matrix<weight, Kernels, W, H>; ///< The type of one output
    using input_t      = std::vector<input_one_t>;                    ///< The type of the input
    using output_t     = std::vector<output_one_t>;                   ///< The type of the output

    etl::fast_matrix<weight, Kernels> gamma;
    etl::fast_matrix<weight, Kernels> beta;

    etl::fast_matrix<weight, Kernels> mean;
    etl::fast_matrix<weight, Kernels> var;

    etl::fast_matrix<weight, Kernels> last_mean;
    etl::fast_matrix<weight, Kernels> last_var;
    etl::fast_matrix<weight, Kernels> inv_var;

    etl::dyn_matrix<weight, 4> input_pre; /// B x K x W x H

    weight momentum = 0.9;

    //Backup gamma and beta
    std::unique_ptr<etl::fast_matrix<weight, Kernels>> bak_gamma; ///< Backup gamma
    std::unique_ptr<etl::fast_matrix<weight, Kernels>> bak_beta;  ///< Backup beta

    batch_normalization_4d_layer_impl() : base_type() {
        gamma = 1.0;
        beta = 0.0;
    }

    /*!
     * \brief Returns a string representation of the layer
     */
    static std::string to_short_string([[maybe_unused]] std::string pre = "") {
        return "batch_norm";
    }

    /*!
     * \brief Returns a string representation of the layer
     */
    static std::string to_full_string([[maybe_unused]] std::string pre = "") {
        return "batch_norm";
    }

    /*!
     * \brief Return the number of trainable parameters of this network.
     * \return The the number of trainable parameters of this network.
     */
    static constexpr size_t parameters() noexcept {
        return 4 * Kernels;
    }

    /*!
     * \brief Return the size of the input of this layer
     * \return The size of the input of this layer
     */
    static constexpr size_t input_size() noexcept {
        return Kernels * W * H;
    }

    /*!
     * \brief Return the size of the output of this layer
     * \return The size of the output of this layer
     */
    static constexpr size_t output_size() noexcept {
        return Kernels * W * H;
    }

    /*!
     * \brief Returns the output shape
     * \return an std::string containing the description of the output shape
     */
    std::vector<size_t> output_shape([[maybe_unused]] const std::vector<size_t>& input_shape) const {
        return {Kernels, W, H};
    }

    using base_type::test_forward_batch;
    using base_type::train_forward_batch;

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void forward_batch(Output& output, const Input& input) const {
        test_forward_batch(output, input);
    }

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void test_forward_batch(Output& output, const Input& input) const {
        dll::auto_timer timer("bn:4d:test:forward");

        const auto B = etl::dim<0>(input);

        auto inv_var = etl::force_temporary(1.0 / etl::sqrt(var + e));

        for (size_t b = 0; b < B; ++b) {
            for (size_t k = 0; k < Kernels; ++k) {
                output(b)(k) = (gamma(k) >> ((input(b)(k) - mean(k)) >> inv_var(k))) + beta(k);
            }
        }
    }

    /*!
     * \brief Apply the layer to the batch of input
     * \param output The batch of output
     * \param input The batch of input to apply the layer to
     */
    template <typename Input, typename Output>
    void train_forward_batch(Output& output, const Input& input) {
        dll::auto_timer timer("bn:4d:train:forward");

        const auto B = etl::dim<0>(input);
        const auto S = B * W * H;

        // Compute the mean of the mini-batch
        last_mean = etl::bias_batch_mean_4d(input);

        // Compute the variance of the mini-batch
        last_var  = 0;

        for (size_t b = 0; b < B; ++b) {
            for (size_t k = 0; k < Kernels; ++k) {
                last_var(k) += etl::sum((input(b)(k) - last_mean(k)) >> (input(b)(k) - last_mean(k)));
            }
        }

        last_var /= S;

        inv_var  = 1.0 / etl::sqrt(last_var + e);

        input_pre.inherit_if_null(input);

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                input_pre(b)(k) = (input(b)(k) - last_mean(k)) >> inv_var(k);
                output(b)(k)    = (gamma(k) >> input_pre(b)(k)) + beta(k);
            }
        }

        //// Update the current mean and variance
        mean = momentum * mean + (1.0 - momentum) * last_mean;
        var  = momentum * var + (1.0 - momentum) * (S / (S - 1) * last_var);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template <typename C>
    void adapt_errors([[maybe_unused]] C& context) const {}

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename HH, typename C>
    void backward_batch(HH&& output, C& context) const {
        dll::unsafe_auto_timer timer("bn:4d:backward");

        const auto B = etl::dim<0>(context.input);
        const auto S = B * W * H;

        auto dxhat = etl::force_temporary_dim_only(context.errors);

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                dxhat(b)(k) = context.errors(b)(k) >> gamma(k);
            }
        }

        auto dxhat_l      = etl::bias_batch_sum_4d(dxhat);
        auto dxhat_xhat_l = etl::bias_batch_sum_4d(dxhat >> input_pre);

        *dxhat_l;
        *dxhat_xhat_l;

        for(size_t b = 0; b < B; ++b){
            for (size_t k = 0; k < Kernels; ++k) {
                output(b)(k) = ((1.0 / S) * inv_var(k)) >> (S * dxhat(b)(k) - dxhat_l(k) - (input_pre(b)(k) >> dxhat_xhat_l(k)));
            }
        }
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        dll::unsafe_auto_timer timer("bn:4d:gradients");

        // Gradients of gamma
        std::get<0>(context.up.context)->grad = etl::bias_batch_sum_4d(input_pre >> context.errors);

        // Gradients of beta
        std::get<1>(context.up.context)->grad = etl::bias_batch_sum_4d(context.errors);
    }

    /*!
     * \brief Prepare one empty output for this layer
     * \return an empty ETL matrix suitable to store one output of this layer
     *
     * \tparam Input The type of one Input
     */
    template <typename InputType>
    output_one_t prepare_one_output() const {
        return {};
    }

    /*!
     * \brief Prepare a set of empty outputs for this layer
     * \param samples The number of samples to prepare the output for
     * \return a container containing empty ETL matrices suitable to store samples output of this layer
     * \tparam Input The type of one input
     */
    template <typename InputType>
    static output_t prepare_output(size_t samples) {
        return output_t{samples};
    }

    /*!
     * \brief Initialize the dynamic version of the layer from the fast version of the layer
     * \param dyn Reference to the dynamic version of the layer that needs to be initialized
     */
    template<typename DLayer>
    static void dyn_init(DLayer& dyn){
        dyn.init_layer(Kernels, W, H);
    }

    /*!
     * \brief Returns the trainable variables of this layer.
     * \return a tuple containing references to the variables of this layer
     */
    decltype(auto) trainable_parameters(){
        return std::make_tuple(std::ref(gamma), std::ref(beta));
    }

    /*!
     * \brief Returns the trainable variables of this layer.
     * \return a tuple containing references to the variables of this layer
     */
    decltype(auto) trainable_parameters() const {
        return std::make_tuple(std::cref(gamma), std::cref(beta));
    }

    /*!
     * \brief Backup the weights in the secondary weights matrix
     */
    void backup_weights() {
        unique_safe_get(bak_gamma) = gamma;
        unique_safe_get(bak_beta)  = beta;
    }

    /*!
     * \brief Restore the weights from the secondary weights matrix
     */
    void restore_weights() {
        gamma = *bak_gamma;
        beta  = *bak_beta;
    }
};

// Declare the traits for the layer

template<typename Desc>
struct layer_base_traits<batch_normalization_4d_layer_impl<Desc>> {
    static constexpr bool is_neural     = true; ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false; ///< Indicates if the layer is dense
    static constexpr bool is_conv       = false; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = false; ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false; ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false;  ///< Indicates if the layer is a transform layer
    static constexpr bool is_recurrent  = false; ///< Indicates if the layer is a recurrent layer
    static constexpr bool is_multi      = false; ///< Indicates if the layer is a multi-layer layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief Specialization of sgd_context for batch_normalization_4d_layer_impl
 */
template <typename DBN, typename Desc, size_t L>
struct sgd_context<DBN, batch_normalization_4d_layer_impl<Desc>, L> {
    using layer_t = batch_normalization_4d_layer_impl<Desc>; ///< The current layer type
    using weight  = typename layer_t::weight;           ///< The data type for this layer

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> input;  ///< A batch of input
    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> output; ///< A batch of output
    etl::fast_matrix<weight, batch_size, layer_t::Kernels, layer_t::W, layer_t::H> errors; ///< A batch of errors

    sgd_context(const layer_t& /*layer*/){}
};

} //end of dll namespace
<|endoftext|>