<commit_before>/*------------MD.cpp----------------------------------------------------------//
*
*             MD.cpp -- a simple event-driven MD simulation
*
* Purpose: Figure out the pressure on the interior of a box based on
*          Boltzmann's theory and stuff
*
*   Notes: This simulation will predominantly follow the logic of the link in
*          the README file
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <fstream>
#include <random>
//#include <algorithm>

namespace sim{
	/* putting our stuff in its own namespace so we can call "time" "time"
	   without colliding with names from the standard library */
	using time = double;
}

/*----------------------------------------------------------------------------//
* STRUCTS AND FUNCTIONS
*-----------------------------------------------------------------------------*/

// Holds our data in a central struct, to be called mainly in a vector
struct Particle{
	int PID;
	sim::time ts;
	double pos_x, pos_y, pos_z, vel_x, vel_y, vel_z;
};

// holds interaction data
struct Interaction{
	sim::time rtime;
	int part1, part2;
};

// Makes starting data
std::vector<Particle> populate(int pnum, double box_length, double max_vel);

// Makes the list for our simulation later, required starting data
std::vector<Interaction> make_list(const std::vector<Particle> &curr_data,
                                   double box_length, double radius);

// This performs our MD simulation with a vector of interactions
// Also writes simulation to file, specified by README
void simulate(std::vector<int> interactions, std::vector<Particle> curr_data);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(void){

    int pnum = 100;
    double box_length = 10, max_vel = 0.01;

    std::vector<Particle> curr_data = populate(pnum, box_length, max_vel);

    for (auto &p : curr_data){

        std::cout << p.pos_x << std::endl;

    }

    return 0;
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Makes starting data
std::vector<Particle> populate(int pnum, double box_length, double max_vel){
    std::vector<Particle> curr_data(pnum);

    // static to create only 1 random_device
    static std::random_device rd;
    static std::mt19937 gen(rd());

    /* instead of doing % and * to get the correct distribution we directly
       specify which distribution we want */

    std::uniform_real_distribution<double>
        box_length_distribution(0, box_length);
    std::uniform_real_distribution<double>
       max_vel_distribution(0, max_vel);

    int PID_counter = 0;
    for (auto &p : curr_data){ //read: for all particles p in curr_data
        p.ts = 0;
        p.PID = PID_counter++;

        for (auto &pos : { &p.pos_x, &p.pos_y, &p.pos_z })
           *pos = box_length_distribution(gen);
        for (auto &vel : { &p.vel_x, &p.vel_y, &p.vel_z })
           *vel = max_vel_distribution(gen);
    }

return curr_data;
}

// Makes the list for our simulation later, required starting data
// Step 1: Check interactions between Particles, based on README link
// Step 2: Update list.
// Step 3: Sort list, lowest first
std::vector<Interaction> make_list(const std::vector<Particle> &curr_data,
                                   double box_length, double radius){
    /* passing curr_data as const reference to avoid the copy and accidental
    overwriting */
    std::vector<Interaction> list;
    Interaction test;
    int i = 0,j = 0;

    // Step 1 -- find interactions
    for (auto &ip : curr_data){
        for (auto &jp : curr_data){
            double del_x = ip.pos_x - jp.pos_x;
            double del_y = ip.pos_y - jp.pos_y;
            double del_z = ip.pos_z - jp.pos_y;

            double del_vx = ip.vel_x - jp.vel_y;
            double del_vy = ip.vel_y - jp.vel_y;
            double del_vz = ip.vel_z - jp.vel_z;

            double r_prime = 2 * radius;

            double rad_d = (pow(del_vx * del_x + del_vy * del_y
                                 + del_vz * del_z, 2)
                    - 4 * (del_vx * del_vx + del_vy * del_vy + del_vz * del_vz)
                    * (del_x * del_x + del_y * del_y + del_z * del_z
                       - r_prime * r_prime));

            sim::time check;
            if (del_x * del_vx >= 0 && del_y * del_vy >= 0 &&
                del_z * del_vz >= 0){
                check = 0;
            }

            else if (rad_d > 0){
                check = 0;
            }

            else {
                check = (-(del_vx * del_x + del_vy * del_y + del_vz * del_z)
                        + sqrt(rad_d)) / (2 * (del_vx * del_vx + del_vz * del_vz
                        + del_vy * del_vy));
            }

            // Step 2 -- update list
            if (check != 0){
                test.rtime = check;
                test.part1 = i;
                test.part2 = j;
                list.push_back(test);
            }
            j++;
        }
        i++;
    }

    // Step 3 -- sort the list
/*
    // std::sort()
    vector <Interaction> dummy;

    for (auto &ele : list){
    }

std::sort(std::begin(vec), std::end(vec), [](const Particle
                &lhs, const Particle &rhs){ return lhs.ts < rhs.ts; });
*/
    return list;
}

// This performs our MD simulation with a vector of interactions
// Also writes simulation to file, specified by README
// Note: Time-loop here
void simulate(std::vector<int> interactions, std::vector<Particle> curr_data){

}

<commit_msg>pulled definitions out of loop.<commit_after>/*------------MD.cpp----------------------------------------------------------//
*
*             MD.cpp -- a simple event-driven MD simulation
*
* Purpose: Figure out the pressure on the interior of a box based on
*          Boltzmann's theory and stuff
*
*   Notes: This simulation will predominantly follow the logic of the link in
*          the README file
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <fstream>
#include <random>
//#include <algorithm>

namespace sim{
	/* putting our stuff in its own namespace so we can call "time" "time"
	   without colliding with names from the standard library */
	using time = double;
}

/*----------------------------------------------------------------------------//
* STRUCTS AND FUNCTIONS
*-----------------------------------------------------------------------------*/

// Holds our data in a central struct, to be called mainly in a vector
struct Particle{
	int PID;
	sim::time ts;
	double pos_x, pos_y, pos_z, vel_x, vel_y, vel_z;
};

// holds interaction data
struct Interaction{
	sim::time rtime;
	int part1, part2;
};

// Makes starting data
std::vector<Particle> populate(int pnum, double box_length, double max_vel);

// Makes the list for our simulation later, required starting data
std::vector<Interaction> make_list(const std::vector<Particle> &curr_data,
                                   double box_length, double radius);

// This performs our MD simulation with a vector of interactions
// Also writes simulation to file, specified by README
void simulate(std::vector<int> interactions, std::vector<Particle> curr_data);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(void){

    int pnum = 100;
    double box_length = 10, max_vel = 0.01;

    std::vector<Particle> curr_data = populate(pnum, box_length, max_vel);

    for (auto &p : curr_data){

        std::cout << p.pos_x << std::endl;

    }

    return 0;
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Makes starting data
std::vector<Particle> populate(int pnum, double box_length, double max_vel){
    std::vector<Particle> curr_data(pnum);

    // static to create only 1 random_device
    static std::random_device rd;
    static std::mt19937 gen(rd());

    /* instead of doing % and * to get the correct distribution we directly
       specify which distribution we want */

    std::uniform_real_distribution<double>
        box_length_distribution(0, box_length);
    std::uniform_real_distribution<double>
       max_vel_distribution(0, max_vel);

    int PID_counter = 0;
    for (auto &p : curr_data){ //read: for all particles p in curr_data
        p.ts = 0;
        p.PID = PID_counter++;

        for (auto &pos : { &p.pos_x, &p.pos_y, &p.pos_z })
           *pos = box_length_distribution(gen);
        for (auto &vel : { &p.vel_x, &p.vel_y, &p.vel_z })
           *vel = max_vel_distribution(gen);
    }

return curr_data;
}

// Makes the list for our simulation later, required starting data
// Step 1: Check interactions between Particles, based on README link
// Step 2: Update list.
// Step 3: Sort list, lowest first
std::vector<Interaction> make_list(const std::vector<Particle> &curr_data,
                                   double box_length, double radius){
    /* passing curr_data as const reference to avoid the copy and accidental
    overwriting */
    std::vector<Interaction> list;
    Interaction test;
    int i = 0,j = 0;
    double del_x, del_y, del_z, del_vx, del_vy, del_vz, r_prime, rad_d;

    // Step 1 -- find interactions
    for (auto &ip : curr_data){
        for (auto &jp : curr_data){
            del_x = ip.pos_x - jp.pos_x;
            del_y = ip.pos_y - jp.pos_y;
            del_z = ip.pos_z - jp.pos_y;

            del_vx = ip.vel_x - jp.vel_y;
            del_vy = ip.vel_y - jp.vel_y;
            del_vz = ip.vel_z - jp.vel_z;

            r_prime = 2 * radius;

            rad_d = (pow(del_vx * del_x + del_vy * del_y
                                 + del_vz * del_z, 2)
                    - 4 * (del_vx * del_vx + del_vy * del_vy + del_vz * del_vz)
                    * (del_x * del_x + del_y * del_y + del_z * del_z
                       - r_prime * r_prime));

            sim::time check;
            if (del_x * del_vx >= 0 && del_y * del_vy >= 0 &&
                del_z * del_vz >= 0){
                check = 0;
            }

            else if (rad_d > 0){
                check = 0;
            }

            else {
                check = (-(del_vx * del_x + del_vy * del_y + del_vz * del_z)
                        + sqrt(rad_d)) / (2 * (del_vx * del_vx + del_vz * del_vz
                        + del_vy * del_vy));
            }

            // Step 2 -- update list
            if (check != 0){
                test.rtime = check;
                test.part1 = i;
                test.part2 = j;
                list.push_back(test);
            }
            j++;
        }
        i++;
    }

    // Step 3 -- sort the list
/*
    // std::sort()
    vector <Interaction> dummy;

    for (auto &ele : list){
    }

std::sort(std::begin(vec), std::end(vec), [](const Particle
                &lhs, const Particle &rhs){ return lhs.ts < rhs.ts; });
*/
    return list;
}

// This performs our MD simulation with a vector of interactions
// Also writes simulation to file, specified by README
// Note: Time-loop here
void simulate(std::vector<int> interactions, std::vector<Particle> curr_data){

}

<|endoftext|>


<commit_before>/**
 * Unix Tools For Windows
 *  - date: write the date and time
 *
 * Written in 2013 by Ruben Van Boxem <vanboxem.ruben@gmail.com>
 *
 * To the extent possible under law, the author(s) have dedicated all copyright and related
 * and neighboring rights to this software to the public domain worldwide. This software is
 * distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 *
 */

// Boost includes
#include <boost/program_options.hpp>
  namespace po = boost::program_options;

// C++ includes
#include <iostream>

//Platform includes
#include <io.h>
#include <fcntl.h>
#include <windows.h>

int main()
{
  int argc;
  wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
  DWORD cChars;
  if(argc > 0)
  {
    for(int i=1; i<argc-1; ++i)
    {
      WriteConsoleW(hstdout, argv[i], DWORD(wcslen(argv[i])), &cChars, NULL);
    }
    WriteConsoleW(hstdout, argv[argc-1], DWORD(wcslen(argv[argc-1])), &cChars, NULL);
  }
}
<commit_msg>fix comments in echo.cpp<commit_after>/**
 * Unix Tools For Windows
 *  - echo: write arguments to standard output
 *
 * Written in 2013 by Ruben Van Boxem <vanboxem.ruben@gmail.com>
 *
 * To the extent possible under law, the author(s) have dedicated all copyright and related
 * and neighboring rights to this software to the public domain worldwide. This software is
 * distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 *
 */

// Boost includes
#include <boost/program_options.hpp>
  namespace po = boost::program_options;

// C++ includes
#include <iostream>

//Platform includes
#include <io.h>
#include <fcntl.h>
#include <windows.h>

int main()
{
  int argc;
  wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
  DWORD cChars;
  if(argc > 0)
  {
    for(int i=1; i<argc-1; ++i)
    {
      WriteConsoleW(hstdout, argv[i], DWORD(wcslen(argv[i])), &cChars, NULL);
    }
    WriteConsoleW(hstdout, argv[argc-1], DWORD(wcslen(argv[argc-1])), &cChars, NULL);
  }
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

TEST(SimpleMathTest, Sum) {
  // This test is named "Negative", and belongs to the "FactorialTest"
  // test case.
  EXPECT_EQ(2, 1+1);
  EXPECT_EQ(4, 2+2);
 // EXPECT_EQ(expected, actual)
}

TEST(SimpleMathTest, Difference) {
  EXPECT_EQ(0, 1-1);
  EXPECT_EQ(1, 2-1);
  EXPECT_EQ(2, 3-1);
}

TEST(SimpleMathTest, Multiplication) {
  EXPECT_EQ(1, 1*1);
}
<commit_msg>Removes duplicated test<commit_after><|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

#include "PaddleAPI.h"

#include "PaddleAPIPrivate.h"
#include "paddle/trainer/RemoteParameterUpdater.h"
#include "paddle/trainer/ThreadParameterUpdater.h"

ParameterUpdater::ParameterUpdater() : m(new ParameterUpdaterPrivate()) {}

ParameterUpdater *ParameterUpdater::createLocalUpdater(
    OptimizationConfig *config) {
  auto updater = new ParameterUpdater();
  updater->m->updater.reset(
      new paddle::SgdThreadUpdater(config->m->getConfig()));
  return updater;
}

ParameterUpdater *ParameterUpdater::createRemoteUpdater(
    OptimizationConfig *config, int passCount) {
  auto updater = new ParameterUpdater();
  std::unique_ptr<paddle::ParameterUpdater> localUpdater;
  updater->m->updater.reset(new paddle::RemoteParameterUpdater(
      config->m->getConfig(), passCount, std::move(localUpdater)));
  return updater;
}

ParameterUpdater::~ParameterUpdater() { delete m; }

void ParameterUpdater::init(const GradientMachine &gm) {
  m->updater->init(gm.m->machine->getNonStaticParameters());
}

void ParameterUpdater::startPass() { m->updater->startPass(); }

void ParameterUpdater::finishPass() { m->updater->finishPass(); }

PassType ParameterUpdater::startBatch(size_t batchSize) {
  return m->updater->startBatch((int64_t)batchSize);
}

void ParameterUpdater::finishBatch(float cost) {
  m->updater->finishBatch(cost);
}

void ParameterUpdater::update(Parameter *param) {
  auto paddleParam = param->m->getPtr();
  m->updater->update(paddleParam);
}

void ParameterUpdater::restore() { m->updater->restore(); }

void ParameterUpdater::apply() { m->updater->apply(); }

void ParameterUpdater::catchUpWith() { m->updater->catchUpWith(); }
<commit_msg>udw nullptr as localUpdater<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

#include "PaddleAPI.h"

#include "PaddleAPIPrivate.h"
#include "paddle/trainer/RemoteParameterUpdater.h"
#include "paddle/trainer/ThreadParameterUpdater.h"

ParameterUpdater::ParameterUpdater() : m(new ParameterUpdaterPrivate()) {}

ParameterUpdater *ParameterUpdater::createLocalUpdater(
    OptimizationConfig *config) {
  auto updater = new ParameterUpdater();
  updater->m->updater.reset(
      new paddle::SgdThreadUpdater(config->m->getConfig()));
  return updater;
}

ParameterUpdater *ParameterUpdater::createRemoteUpdater(
    OptimizationConfig *config, int passCount) {
  auto updater = new ParameterUpdater();
  updater->m->updater.reset(new paddle::RemoteParameterUpdater(
      config->m->getConfig(), passCount, nullptr));
  return updater;
}

ParameterUpdater::~ParameterUpdater() { delete m; }

void ParameterUpdater::init(const GradientMachine &gm) {
  m->updater->init(gm.m->machine->getNonStaticParameters());
}

void ParameterUpdater::startPass() { m->updater->startPass(); }

void ParameterUpdater::finishPass() { m->updater->finishPass(); }

PassType ParameterUpdater::startBatch(size_t batchSize) {
  return m->updater->startBatch((int64_t)batchSize);
}

void ParameterUpdater::finishBatch(float cost) {
  m->updater->finishBatch(cost);
}

void ParameterUpdater::update(Parameter *param) {
  auto paddleParam = param->m->getPtr();
  m->updater->update(paddleParam);
}

void ParameterUpdater::restore() { m->updater->restore(); }

void ParameterUpdater::apply() { m->updater->apply(); }

void ParameterUpdater::catchUpWith() { m->updater->catchUpWith(); }
<|endoftext|>


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

#include <QtCore/QDebug>
#include <QtCore/QEventLoop>
#include <QtWebSockets/QWebSocket>
#include <assert.h>

#include "websocket/WebSocketMessagingStub.h"
#include "joynr/system/RoutingTypes/Address.h"
#include "joynr/system/RoutingTypes/WebSocketAddress.h"
#include "joynr/system/RoutingTypes/WebSocketClientAddress.h"
#include "joynr/TypeUtil.h"

namespace joynr
{

joynr_logging::Logger* WebSocketMessagingStubFactory::logger =
        joynr_logging::Logging::getInstance()->getLogger("MSG", "WebSocketMessagingStubFactory");

WebSocketMessagingStubFactory::WebSocketMessagingStubFactory(QObject* parent)
        : QObject(parent), serverStubMap(), clientStubMap(), mutex()
{
}

bool WebSocketMessagingStubFactory::canCreate(
        const joynr::system::RoutingTypes::Address& destAddress)
{
    return dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&destAddress) ||
           dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&destAddress);
}

std::shared_ptr<IMessaging> WebSocketMessagingStubFactory::create(
        const joynr::system::RoutingTypes::Address& destAddress)
{
    // if destination is a WS client address
    if (auto webSocketClientAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&destAddress)) {
        // lookup address
        {
            std::lock_guard<std::mutex> lock(mutex);
            if (clientStubMap.find(*webSocketClientAddress) == clientStubMap.cend()) {
                LOG_ERROR(logger,
                          FormatString("No websocket found for address %1")
                                  .arg(webSocketClientAddress->toString())
                                  .str());
                return std::shared_ptr<IMessaging>();
            }
        }
        return clientStubMap[*webSocketClientAddress];
    }
    // if destination is a WS server address
    if (const system::RoutingTypes::WebSocketAddress* webSocketServerAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&destAddress)) {
        // lookup address
        {
            std::lock_guard<std::mutex> lock(mutex);
            if (serverStubMap.find(*webSocketServerAddress) == serverStubMap.cend()) {
                LOG_ERROR(logger,
                          FormatString("No websocket found for address %1")
                                  .arg(webSocketServerAddress->toString())
                                  .str());
                return std::shared_ptr<IMessaging>();
            }
        }
        return serverStubMap[*webSocketServerAddress];
    }

    return std::shared_ptr<IMessaging>();
}

void WebSocketMessagingStubFactory::addClient(
        const joynr::system::RoutingTypes::WebSocketClientAddress* clientAddress,
        QWebSocket* webSocket)
{
    WebSocketMessagingStub* wsClientStub = new WebSocketMessagingStub(clientAddress, webSocket);
    connect(wsClientStub,
            &WebSocketMessagingStub::closed,
            this,
            &WebSocketMessagingStubFactory::onMessagingStubClosed);
    std::shared_ptr<IMessaging> clientStub(wsClientStub);
    clientStubMap[*clientAddress] = clientStub;
}

void WebSocketMessagingStubFactory::removeClient(
        const joynr::system::RoutingTypes::WebSocketClientAddress& clientAddress)
{
    clientStubMap.erase(clientAddress);
}

void WebSocketMessagingStubFactory::addServer(
        const joynr::system::RoutingTypes::WebSocketAddress& serverAddress,
        QWebSocket* webSocket)
{

    WebSocketMessagingStub* wsServerStub = new WebSocketMessagingStub(
            new system::RoutingTypes::WebSocketAddress(serverAddress), webSocket);
    connect(wsServerStub,
            &WebSocketMessagingStub::closed,
            this,
            &WebSocketMessagingStubFactory::onMessagingStubClosed);
    std::shared_ptr<IMessaging> serverStub(wsServerStub);
    serverStubMap[serverAddress] = serverStub;
}

void WebSocketMessagingStubFactory::onMessagingStubClosed(
        const system::RoutingTypes::Address& address)
{
    LOG_DEBUG(
            logger,
            FormatString("removing messaging stub for address: %1").arg(address.toString()).str());
    // if destination is a WS client address
    if (auto webSocketClientAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&address)) {
        clientStubMap.erase(*webSocketClientAddress);
    } else if (auto webSocketServerAddress =
                       dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&address)) {
        serverStubMap.erase(*webSocketServerAddress);
    }
}

QUrl WebSocketMessagingStubFactory::convertWebSocketAddressToUrl(
        const system::RoutingTypes::WebSocketAddress& address)
{
    return QUrl(QString("%0://%1:%2%3")
                        .arg(QString::fromStdString(
                                     joynr::system::RoutingTypes::WebSocketProtocol::getLiteral(
                                             address.getProtocol())).toLower())
                        .arg(QString::fromStdString(address.getHost()))
                        .arg(address.getPort())
                        .arg(QString::fromStdString(address.getPath())));
}

} // namespace joynr
<commit_msg>[C++] WebSocketMessagingStubFactory check for existing client<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2014 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "WebSocketMessagingStubFactory.h"

#include <QtCore/QDebug>
#include <QtCore/QEventLoop>
#include <QtWebSockets/QWebSocket>
#include <assert.h>

#include "websocket/WebSocketMessagingStub.h"
#include "joynr/system/RoutingTypes/Address.h"
#include "joynr/system/RoutingTypes/WebSocketAddress.h"
#include "joynr/system/RoutingTypes/WebSocketClientAddress.h"
#include "joynr/TypeUtil.h"

namespace joynr
{

joynr_logging::Logger* WebSocketMessagingStubFactory::logger =
        joynr_logging::Logging::getInstance()->getLogger("MSG", "WebSocketMessagingStubFactory");

WebSocketMessagingStubFactory::WebSocketMessagingStubFactory(QObject* parent)
        : QObject(parent), serverStubMap(), clientStubMap(), mutex()
{
}

bool WebSocketMessagingStubFactory::canCreate(
        const joynr::system::RoutingTypes::Address& destAddress)
{
    return dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&destAddress) ||
           dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&destAddress);
}

std::shared_ptr<IMessaging> WebSocketMessagingStubFactory::create(
        const joynr::system::RoutingTypes::Address& destAddress)
{
    // if destination is a WS client address
    if (auto webSocketClientAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&destAddress)) {
        // lookup address
        {
            std::lock_guard<std::mutex> lock(mutex);
            if (clientStubMap.find(*webSocketClientAddress) == clientStubMap.cend()) {
                LOG_ERROR(logger,
                          FormatString("No websocket found for address %1")
                                  .arg(webSocketClientAddress->toString())
                                  .str());
                return std::shared_ptr<IMessaging>();
            }
        }
        return clientStubMap[*webSocketClientAddress];
    }
    // if destination is a WS server address
    if (const system::RoutingTypes::WebSocketAddress* webSocketServerAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&destAddress)) {
        // lookup address
        {
            std::lock_guard<std::mutex> lock(mutex);
            if (serverStubMap.find(*webSocketServerAddress) == serverStubMap.cend()) {
                LOG_ERROR(logger,
                          FormatString("No websocket found for address %1")
                                  .arg(webSocketServerAddress->toString())
                                  .str());
                return std::shared_ptr<IMessaging>();
            }
        }
        return serverStubMap[*webSocketServerAddress];
    }

    return std::shared_ptr<IMessaging>();
}

void WebSocketMessagingStubFactory::addClient(
        const joynr::system::RoutingTypes::WebSocketClientAddress* clientAddress,
        QWebSocket* webSocket)
{

    if (clientStubMap.count(*clientAddress) == 0) {
        WebSocketMessagingStub* wsClientStub = new WebSocketMessagingStub(clientAddress, webSocket);
        connect(wsClientStub,
                &WebSocketMessagingStub::closed,
                this,
                &WebSocketMessagingStubFactory::onMessagingStubClosed);
        std::shared_ptr<IMessaging> clientStub(wsClientStub);
        clientStubMap[*clientAddress] = clientStub;
    } else {
        LOG_ERROR(logger,
                  FormatString("Client with address %1 already exists in the clientStubMap")
                          .arg(clientAddress->toString())
                          .str());
    }
}

void WebSocketMessagingStubFactory::removeClient(
        const joynr::system::RoutingTypes::WebSocketClientAddress& clientAddress)
{
    clientStubMap.erase(clientAddress);
}

void WebSocketMessagingStubFactory::addServer(
        const joynr::system::RoutingTypes::WebSocketAddress& serverAddress,
        QWebSocket* webSocket)
{

    WebSocketMessagingStub* wsServerStub = new WebSocketMessagingStub(
            new system::RoutingTypes::WebSocketAddress(serverAddress), webSocket);
    connect(wsServerStub,
            &WebSocketMessagingStub::closed,
            this,
            &WebSocketMessagingStubFactory::onMessagingStubClosed);
    std::shared_ptr<IMessaging> serverStub(wsServerStub);
    serverStubMap[serverAddress] = serverStub;
}

void WebSocketMessagingStubFactory::onMessagingStubClosed(
        const system::RoutingTypes::Address& address)
{
    LOG_DEBUG(
            logger,
            FormatString("removing messaging stub for address: %1").arg(address.toString()).str());
    // if destination is a WS client address
    if (auto webSocketClientAddress =
                dynamic_cast<const system::RoutingTypes::WebSocketClientAddress*>(&address)) {
        clientStubMap.erase(*webSocketClientAddress);
    } else if (auto webSocketServerAddress =
                       dynamic_cast<const system::RoutingTypes::WebSocketAddress*>(&address)) {
        serverStubMap.erase(*webSocketServerAddress);
    }
}

QUrl WebSocketMessagingStubFactory::convertWebSocketAddressToUrl(
        const system::RoutingTypes::WebSocketAddress& address)
{
    return QUrl(QString("%0://%1:%2%3")
                        .arg(QString::fromStdString(
                                     joynr::system::RoutingTypes::WebSocketProtocol::getLiteral(
                                             address.getProtocol())).toLower())
                        .arg(QString::fromStdString(address.getHost()))
                        .arg(address.getPort())
                        .arg(QString::fromStdString(address.getPath())));
}

} // namespace joynr
<|endoftext|>


<commit_before>#include "mesh.hpp"
#include "shader_suite.hpp"
#include "render_context.hpp"
#include "renderer.hpp"
#include <string.h>

using namespace Util;
using namespace Vulkan;

namespace Granite
{
Hash StaticMesh::get_instance_key() const
{
	Hasher h;
	h.u64(vbo_position->get_cookie());
	h.u32(position_stride);
	h.u32(topology);
	if (vbo_attributes)
	{
		h.u64(vbo_attributes->get_cookie());
		h.u32(attribute_stride);
	}
	if (ibo)
	{
		h.u64(ibo->get_cookie());
		h.u32(ibo_offset);
		h.u32(index_type);
	}
	h.u32(count);
	h.u32(vertex_offset);
	h.u32(position_stride);
	h.u64(material->get_hash());
	for (auto &attr : attributes)
	{
		h.u32(attr.format);
		h.u32(attr.offset);
	}
	return h.get();
}

namespace RenderFunctions
{
static void mesh_set_state(CommandBuffer &cmd, const StaticMeshInfo &info)
{
	cmd.set_program(*info.program);

	if (info.alpha_test)
		cmd.set_multisample_state(false, false, true);

	cmd.set_vertex_binding(0, *info.vbo_position, 0, info.position_stride);
	if (info.vbo_attributes)
		cmd.set_vertex_binding(1, *info.vbo_attributes, 0, info.attribute_stride);

	if (info.ibo)
		cmd.set_index_buffer(*info.ibo, 0, info.index_type);

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (info.attributes[i].format != VK_FORMAT_UNDEFINED)
			cmd.set_vertex_attrib(i, i == 0 ? 0 : 1, info.attributes[i].format, info.attributes[i].offset);

	auto &sampler = cmd.get_device().get_stock_sampler(info.sampler);
	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		if (info.views[i])
			cmd.set_texture(2, i, *info.views[i], sampler);

	cmd.push_constants(&info.fragment, 0, sizeof(info.fragment));
	cmd.set_primitive_topology(info.topology);

	bool primitive_restart = info.ibo && (info.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP || info.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
	cmd.set_primitive_restart(primitive_restart);
	cmd.set_cull_mode(info.two_sided ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT);
}

void debug_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *info = static_cast<const DebugMeshInfo *>(infos->render_info);

	cmd.set_program(*info->program);
	cmd.push_constants(&info->MVP, 0, sizeof(info->MVP));
	cmd.set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
	cmd.set_vertex_attrib(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
	cmd.set_vertex_attrib(1, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0);

	unsigned count = 0;

	for (unsigned i = 0; i < instances; i++)
		count += static_cast<const DebugMeshInstanceInfo *>(infos[i].instance_data)->count;

	vec3 *pos = static_cast<vec3 *>(cmd.allocate_vertex_data(0, count * sizeof(vec3), sizeof(vec3)));
	vec4 *color = static_cast<vec4 *>(cmd.allocate_vertex_data(1, count * sizeof(vec4), sizeof(vec4)));

	count = 0;
	for (unsigned i = 0; i < instances; i++)
	{
		auto &draw = *static_cast<const DebugMeshInstanceInfo *>(infos[i].instance_data);
		memcpy(pos + count, draw.positions, draw.count * sizeof(vec3));
		memcpy(color + count, draw.colors, draw.count * sizeof(vec4));
		count += draw.count;
	}

	cmd.set_depth_bias(true);
	cmd.set_depth_bias(-1.0f, -1.0f);
	cmd.draw(count);
}

void static_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *info = static_cast<const StaticMeshInfo *>(infos->render_info);
	mesh_set_state(cmd, *info);

	unsigned to_render = 0;
	for (unsigned i = 0; i < instances; i += to_render)
	{
		to_render = min<unsigned>(StaticMeshVertex::max_instances, instances - i);

		auto *vertex_data = static_cast<StaticMeshVertex *>(cmd.allocate_constant_data(3, 0, to_render * sizeof(StaticMeshVertex)));
		for (unsigned j = 0; j < to_render; j++)
			vertex_data[j] = static_cast<const StaticMeshInstanceInfo *>(infos[i + j].instance_data)->vertex;

		if (info->ibo)
			cmd.draw_indexed(info->count, to_render, info->ibo_offset, info->vertex_offset, 0);
		else
			cmd.draw(info->count, to_render, info->vertex_offset, 0);
	}
}

void skinned_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *static_info = static_cast<const StaticMeshInfo *>(infos->render_info);
	mesh_set_state(cmd, *static_info);

	for (unsigned i = 0; i < instances; i++)
	{
		auto &info = *static_cast<const SkinnedMeshInstanceInfo *>(infos[i].instance_data);
		auto *world_transforms = static_cast<mat4 *>(cmd.allocate_constant_data(3, 1, sizeof(mat4) * info.num_bones));
		auto *normal_transforms = static_cast<mat4 *>(cmd.allocate_constant_data(3, 2, sizeof(mat4) * info.num_bones));
		memcpy(world_transforms, info.world_transforms, sizeof(mat4) * info.num_bones);
		memcpy(normal_transforms, info.normal_transforms, sizeof(mat4) * info.num_bones);

		if (static_info->ibo)
			cmd.draw_indexed(static_info->count, 1, static_info->ibo_offset, static_info->vertex_offset, 0);
		else
			cmd.draw(static_info->count, 1, static_info->vertex_offset, 0);
	}
}
}

void StaticMesh::fill_render_info(StaticMeshInfo &info) const
{
	info.vbo_attributes = vbo_attributes.get();
	info.vbo_position = vbo_position.get();
	info.position_stride = position_stride;
	info.attribute_stride = attribute_stride;
	info.vertex_offset = vertex_offset;

	info.ibo = ibo.get();
	info.ibo_offset = ibo_offset;
	info.index_type = index_type;
	info.count = count;
	info.sampler = material->sampler;

	info.fragment.roughness = material->roughness;
	info.fragment.metallic = material->metallic;
	info.fragment.emissive = vec4(material->emissive, 0.0f);
	info.fragment.base_color = material->base_color;
	info.fragment.lod_bias = material->lod_bias;

	info.topology = topology;
	info.two_sided = material->two_sided;
	info.alpha_test = material->pipeline == DrawPipeline::AlphaTest;

	memcpy(info.attributes, attributes, sizeof(attributes));
	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		info.views[i] = material->textures[i] ? &material->textures[i]->get_image()->get_view() : nullptr;
}

void StaticMesh::get_render_info(const RenderContext &context, const CachedSpatialTransformComponent *transform, RenderQueue &queue) const
{
	auto type = material->pipeline == DrawPipeline::AlphaBlend ? Queue::Transparent : Queue::Opaque;
	uint32_t attrs = 0;
	uint32_t textures = 0;

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (attributes[i].format != VK_FORMAT_UNDEFINED)
			attrs |= 1u << i;

	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		if (material->textures[i])
			textures |= 1u << i;

	Hasher h;
	h.u32(attrs);
	h.u32(textures);
	h.u32(ecast(material->pipeline));
	auto pipe_hash = h.get();

	h.u64(material->get_hash());
	h.u64(vbo_position->get_cookie());

	auto instance_key = get_instance_key();
	auto sorting_key = RenderInfo::get_sort_key(context, type, pipe_hash, h.get(), transform->world_aabb.get_center());

	auto *instance_data = queue.allocate_one<StaticMeshInstanceInfo>();
	instance_data->vertex.Model = transform->transform->world_transform;
	instance_data->vertex.Normal = transform->transform->normal_transform;

	auto *mesh_info = queue.push<StaticMeshInfo>(type, instance_key, sorting_key,
	                                             RenderFunctions::static_mesh_render,
	                                             instance_data);

	if (mesh_info)
	{
		fill_render_info(*mesh_info);
		mesh_info->program = queue.get_shader_suites()[ecast(RenderableType::Mesh)].get_program(material->pipeline, attrs,
		                                                                              textures).get();
	}
}

void SkinnedMesh::get_render_info(const RenderContext &context, const CachedSpatialTransformComponent *transform, RenderQueue &queue) const
{
	auto type = material->pipeline == DrawPipeline::AlphaBlend ? Queue::Transparent : Queue::Opaque;
	uint32_t attrs = 0;
	uint32_t textures = 0;

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (attributes[i].format != VK_FORMAT_UNDEFINED)
			attrs |= 1u << i;

	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		if (material->textures[i])
			textures |= 1u << i;

	Hasher h;
	h.u32(attrs);
	h.u32(textures);
	h.u32(ecast(material->pipeline));
	auto pipe_hash = h.get();

	h.u64(material->get_hash());
	h.u64(vbo_position->get_cookie());

	auto instance_key = get_instance_key() ^ 1;
	auto sorting_key = RenderInfo::get_sort_key(context, type, pipe_hash, h.get(), transform->world_aabb.get_center());

	auto *instance_data = queue.allocate_one<SkinnedMeshInstanceInfo>();

	unsigned num_bones = transform->skin_transform->bone_world_transforms.size();
	instance_data->num_bones = num_bones;
	instance_data->world_transforms = queue.allocate_many<mat4>(num_bones);
	instance_data->normal_transforms = queue.allocate_many<mat4>(num_bones);
	memcpy(instance_data->world_transforms, transform->skin_transform->bone_world_transforms.data(), num_bones * sizeof(mat4));
	memcpy(instance_data->normal_transforms, transform->skin_transform->bone_normal_transforms.data(), num_bones * sizeof(mat4));

	auto *mesh_info = queue.push<StaticMeshInfo>(type, instance_key, sorting_key,
	                                             RenderFunctions::skinned_mesh_render,
	                                             instance_data);

	if (mesh_info)
	{
		fill_render_info(*mesh_info);
		mesh_info->program = queue.get_shader_suites()[ecast(RenderableType::Mesh)].get_program(material->pipeline, attrs,
		                                                                              textures).get();
	}
}

void StaticMesh::reset()
{
	vbo_attributes.reset();
	vbo_position.reset();
	ibo.reset();
	material.reset();
}
}
<commit_msg>Some minor opts.<commit_after>#include "mesh.hpp"
#include "shader_suite.hpp"
#include "render_context.hpp"
#include "renderer.hpp"
#include <string.h>

using namespace Util;
using namespace Vulkan;

namespace Granite
{
Hash StaticMesh::get_instance_key() const
{
	Hasher h;
	h.u64(vbo_position->get_cookie());
	h.u32(position_stride);
	h.u32(topology);
	if (vbo_attributes)
	{
		h.u64(vbo_attributes->get_cookie());
		h.u32(attribute_stride);
	}
	if (ibo)
	{
		h.u64(ibo->get_cookie());
		h.u32(ibo_offset);
		h.u32(index_type);
	}
	h.u32(count);
	h.u32(vertex_offset);
	h.u32(position_stride);
	h.u64(material->get_hash());
	for (auto &attr : attributes)
	{
		h.u32(attr.format);
		h.u32(attr.offset);
	}
	return h.get();
}

namespace RenderFunctions
{
static void mesh_set_state(CommandBuffer &cmd, const StaticMeshInfo &info)
{
	cmd.set_program(*info.program);

	if (info.alpha_test)
		cmd.set_multisample_state(false, false, true);

	cmd.set_vertex_binding(0, *info.vbo_position, 0, info.position_stride);
	if (info.vbo_attributes)
		cmd.set_vertex_binding(1, *info.vbo_attributes, 0, info.attribute_stride);

	if (info.ibo)
		cmd.set_index_buffer(*info.ibo, 0, info.index_type);

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (info.attributes[i].format != VK_FORMAT_UNDEFINED)
			cmd.set_vertex_attrib(i, i == 0 ? 0 : 1, info.attributes[i].format, info.attributes[i].offset);

	auto &sampler = cmd.get_device().get_stock_sampler(info.sampler);
	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		if (info.views[i])
			cmd.set_texture(2, i, *info.views[i], sampler);

	cmd.push_constants(&info.fragment, 0, sizeof(info.fragment));
	cmd.set_primitive_topology(info.topology);

	bool primitive_restart = info.ibo && (info.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP || info.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
	cmd.set_primitive_restart(primitive_restart);
	cmd.set_cull_mode(info.two_sided ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT);
}

void debug_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *info = static_cast<const DebugMeshInfo *>(infos->render_info);

	cmd.set_program(*info->program);
	cmd.push_constants(&info->MVP, 0, sizeof(info->MVP));
	cmd.set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
	cmd.set_vertex_attrib(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
	cmd.set_vertex_attrib(1, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0);

	unsigned count = 0;

	for (unsigned i = 0; i < instances; i++)
		count += static_cast<const DebugMeshInstanceInfo *>(infos[i].instance_data)->count;

	vec3 *pos = static_cast<vec3 *>(cmd.allocate_vertex_data(0, count * sizeof(vec3), sizeof(vec3)));
	vec4 *color = static_cast<vec4 *>(cmd.allocate_vertex_data(1, count * sizeof(vec4), sizeof(vec4)));

	count = 0;
	for (unsigned i = 0; i < instances; i++)
	{
		auto &draw = *static_cast<const DebugMeshInstanceInfo *>(infos[i].instance_data);
		memcpy(pos + count, draw.positions, draw.count * sizeof(vec3));
		memcpy(color + count, draw.colors, draw.count * sizeof(vec4));
		count += draw.count;
	}

	cmd.set_depth_bias(true);
	cmd.set_depth_bias(-1.0f, -1.0f);
	cmd.draw(count);
}

void static_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *info = static_cast<const StaticMeshInfo *>(infos->render_info);
	mesh_set_state(cmd, *info);

	unsigned to_render = 0;
	for (unsigned i = 0; i < instances; i += to_render)
	{
		to_render = min<unsigned>(StaticMeshVertex::max_instances, instances - i);

		auto *vertex_data = static_cast<StaticMeshVertex *>(cmd.allocate_constant_data(3, 0, to_render * sizeof(StaticMeshVertex)));
		for (unsigned j = 0; j < to_render; j++)
			vertex_data[j] = static_cast<const StaticMeshInstanceInfo *>(infos[i + j].instance_data)->vertex;

		if (info->ibo)
			cmd.draw_indexed(info->count, to_render, info->ibo_offset, info->vertex_offset, 0);
		else
			cmd.draw(info->count, to_render, info->vertex_offset, 0);
	}
}

void skinned_mesh_render(CommandBuffer &cmd, const RenderQueueData *infos, unsigned instances)
{
	auto *static_info = static_cast<const StaticMeshInfo *>(infos->render_info);
	mesh_set_state(cmd, *static_info);

	for (unsigned i = 0; i < instances; i++)
	{
		auto &info = *static_cast<const SkinnedMeshInstanceInfo *>(infos[i].instance_data);
		auto *world_transforms = static_cast<mat4 *>(cmd.allocate_constant_data(3, 1, sizeof(mat4) * info.num_bones));
		auto *normal_transforms = static_cast<mat4 *>(cmd.allocate_constant_data(3, 2, sizeof(mat4) * info.num_bones));
		memcpy(world_transforms, info.world_transforms, sizeof(mat4) * info.num_bones);
		memcpy(normal_transforms, info.normal_transforms, sizeof(mat4) * info.num_bones);

		if (static_info->ibo)
			cmd.draw_indexed(static_info->count, 1, static_info->ibo_offset, static_info->vertex_offset, 0);
		else
			cmd.draw(static_info->count, 1, static_info->vertex_offset, 0);
	}
}
}

void StaticMesh::fill_render_info(StaticMeshInfo &info) const
{
	info.vbo_attributes = vbo_attributes.get();
	info.vbo_position = vbo_position.get();
	info.position_stride = position_stride;
	info.attribute_stride = attribute_stride;
	info.vertex_offset = vertex_offset;

	info.ibo = ibo.get();
	info.ibo_offset = ibo_offset;
	info.index_type = index_type;
	info.count = count;
	info.sampler = material->sampler;

	info.fragment.roughness = material->roughness;
	info.fragment.metallic = material->metallic;
	info.fragment.emissive = vec4(material->emissive, 0.0f);
	info.fragment.base_color = material->base_color;
	info.fragment.lod_bias = material->lod_bias;

	info.topology = topology;
	info.two_sided = material->two_sided;
	info.alpha_test = material->pipeline == DrawPipeline::AlphaTest;

	memcpy(info.attributes, attributes, sizeof(attributes));
	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		info.views[i] = material->textures[i] ? &material->textures[i]->get_image()->get_view() : nullptr;
}

void StaticMesh::get_render_info(const RenderContext &context, const CachedSpatialTransformComponent *transform, RenderQueue &queue) const
{
	auto type = material->pipeline == DrawPipeline::AlphaBlend ? Queue::Transparent : Queue::Opaque;
	uint32_t attrs = 0;

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (attributes[i].format != VK_FORMAT_UNDEFINED)
			attrs |= 1u << i;

	Hasher h;
	h.u32(attrs);
	h.u32(ecast(material->pipeline));
	auto pipe_hash = h.get();

	h.u64(material->get_hash());
	h.u64(vbo_position->get_cookie());

	auto instance_key = get_instance_key();
	auto sorting_key = RenderInfo::get_sort_key(context, type, pipe_hash, h.get(), transform->world_aabb.get_center());

	auto *t = transform->transform;
	auto *instance_data = queue.allocate_one<StaticMeshInstanceInfo>();
	instance_data->vertex.Model = t->world_transform;
	instance_data->vertex.Normal = t->normal_transform;

	auto *mesh_info = queue.push<StaticMeshInfo>(type, instance_key, sorting_key,
	                                             RenderFunctions::static_mesh_render,
	                                             instance_data);

	if (mesh_info)
	{
		uint32_t textures = 0;
		for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
			if (material->textures[i])
				textures |= 1u << i;

		fill_render_info(*mesh_info);
		mesh_info->program = queue.get_shader_suites()[ecast(RenderableType::Mesh)].get_program(material->pipeline, attrs,
		                                                                              textures).get();
	}
}

void SkinnedMesh::get_render_info(const RenderContext &context, const CachedSpatialTransformComponent *transform, RenderQueue &queue) const
{
	auto type = material->pipeline == DrawPipeline::AlphaBlend ? Queue::Transparent : Queue::Opaque;
	uint32_t attrs = 0;
	uint32_t textures = 0;

	for (unsigned i = 0; i < ecast(MeshAttribute::Count); i++)
		if (attributes[i].format != VK_FORMAT_UNDEFINED)
			attrs |= 1u << i;

	for (unsigned i = 0; i < ecast(Material::Textures::Count); i++)
		if (material->textures[i])
			textures |= 1u << i;

	Hasher h;
	h.u32(attrs);
	h.u32(textures);
	h.u32(ecast(material->pipeline));
	auto pipe_hash = h.get();

	h.u64(material->get_hash());
	h.u64(vbo_position->get_cookie());

	auto instance_key = get_instance_key() ^ 1;
	auto sorting_key = RenderInfo::get_sort_key(context, type, pipe_hash, h.get(), transform->world_aabb.get_center());

	auto *instance_data = queue.allocate_one<SkinnedMeshInstanceInfo>();

	unsigned num_bones = transform->skin_transform->bone_world_transforms.size();
	instance_data->num_bones = num_bones;
	instance_data->world_transforms = queue.allocate_many<mat4>(num_bones);
	instance_data->normal_transforms = queue.allocate_many<mat4>(num_bones);
	memcpy(instance_data->world_transforms, transform->skin_transform->bone_world_transforms.data(), num_bones * sizeof(mat4));
	memcpy(instance_data->normal_transforms, transform->skin_transform->bone_normal_transforms.data(), num_bones * sizeof(mat4));

	auto *mesh_info = queue.push<StaticMeshInfo>(type, instance_key, sorting_key,
	                                             RenderFunctions::skinned_mesh_render,
	                                             instance_data);

	if (mesh_info)
	{
		fill_render_info(*mesh_info);
		mesh_info->program = queue.get_shader_suites()[ecast(RenderableType::Mesh)].get_program(material->pipeline, attrs,
		                                                                              textures).get();
	}
}

void StaticMesh::reset()
{
	vbo_attributes.reset();
	vbo_position.reset();
	ibo.reset();
	material.reset();
}
}
<|endoftext|>


<commit_before>/*
 *  VHDL code generation for statements.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cstring>
#include <cassert>
#include <sstream>

/*
 * Generate VHDL for the $display system task.
 * This is implemented using the functions in std.textio. Each
 * parameter is written to a line variable in the process and
 * then the line is written to the special variable `Output'
 * (which represents the console). Subsequent $displays will
 * use the same line variable.
 *
 * It's possible, although quite unlikely, that there will be
 * name collision with an existing variable called
 * `Verilog_Display_Line' -- do something about this?
 */
static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
{
   // Add the package requirement to the containing entity
   proc->get_parent()->get_parent()->requires_package("std.textio");

   const char *display_line = "Verilog_Display_Line";

   if (!proc->have_declared_var(display_line)) {
      vhdl_type *line_type = new vhdl_scalar_type("Line");
      vhdl_var_decl *line_var =
         new vhdl_var_decl(display_line, line_type);
      line_var->set_comment("For generating $display output");
      proc->add_decl(line_var);
   }

   // Write the data into the line
   int count = ivl_stmt_parm_count(stmt);
   for (int i = 0; i < count; i++) {
      // $display may have an empty parameter, in which case
      // the expression will be null
      // The behaviour here seems to be to output a space
      ivl_expr_t net = ivl_stmt_parm(stmt, i);
      vhdl_expr *e = NULL;
      if (net) {
         vhdl_expr *base = translate_expr(net);
         if (NULL == base)
            return 1;

         // Need to add a call to Type'Image for types not
         // supported by std.textio
         if (base->get_type()->get_name() != "String") {
            std::string name(base->get_type()->get_name());
            name += "'Image";

            vhdl_fcall *cast
               = new vhdl_fcall(name.c_str(), vhdl_scalar_type::string());
            cast->add_expr(base);
            e = cast;
         }
         else
            e = base;
      }
      else
         e = new vhdl_const_string(" ");

      vhdl_pcall_stmt *write = new vhdl_pcall_stmt("Write");
      vhdl_var_ref *ref =
         new vhdl_var_ref(display_line, vhdl_scalar_type::line());
      write->add_expr(ref);
      write->add_expr(e);

      proc->add_stmt(write);
   }

   // WriteLine(Output, Verilog_Display_Line)
   vhdl_pcall_stmt *write_line = new vhdl_pcall_stmt("WriteLine");
   vhdl_var_ref *output_ref =
      new vhdl_var_ref("std.textio.Output", new vhdl_scalar_type("File"));
   write_line->add_expr(output_ref);
   vhdl_var_ref *ref =
      new vhdl_var_ref(display_line, vhdl_scalar_type::line());
   write_line->add_expr(ref);
   proc->add_stmt(write_line);

   return 0;
}

/*
 * Generate VHDL for system tasks (like $display). Not all of
 * these are supported.
 */
static int draw_stask(vhdl_process *proc, ivl_statement_t stmt)
{
   const char *name = ivl_stmt_name(stmt);

   if (strcmp(name, "$display") == 0)
      return draw_stask_display(proc, stmt);
   else {
      error("No VHDL translation for system task %s", name);
      return 0;
   }
}

/*
 * Generate VHDL for a block of Verilog statements. This doesn't
 * actually do anything, other than recursively translate the
 * block's statements and add them to the process. This is OK as
 * `begin' and `end process' function like a Verilog block.
 */
static int draw_block(vhdl_process *proc, ivl_statement_t stmt)
{
   int count = ivl_stmt_block_count(stmt);
   for (int i = 0; i < count; i++) {
      if (draw_stmt(proc, ivl_stmt_block_stmt(stmt, i)) != 0)
         return 1;
   }
   return 0;
}

/*
 * A no-op statement. This corresponds to a `null' statement in
 * VHDL.
 */
static int draw_noop(vhdl_process *proc, ivl_statement_t stmt)
{
   proc->add_stmt(new vhdl_null_stmt());
   return 0;
}

/*
 * A non-blocking assignment inside a process. The semantics for
 * this are essentially the same as VHDL's non-blocking signal
 * assignment.
 */
static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt)
{
   int nlvals = ivl_stmt_lvals(stmt);
   if (nlvals != 1) {
      error("Can only have 1 lval at the moment (found %d)", nlvals);
      return 1;
   }

   ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
   ivl_signal_t sig;
   if ((sig = ivl_lval_sig(lval))) {
      const char *signame = ivl_signal_basename(sig);

      vhdl_decl *decl = proc->get_parent()->get_decl(signame);
      assert(decl);

      vhdl_expr *rhs =
         decl->get_type()->cast(translate_expr(ivl_stmt_rval(stmt)));
      if (NULL == rhs)
         return 1;

      // The type here can be null as it is never actually needed
      vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL);

      proc->add_stmt(new vhdl_nbassign_stmt(lval_ref, rhs));
   }
   else {
      error("Only signals as lvals supported at the moment");
      return 1;
   }

   return 0;
}

/*
 * Delay statements are equivalent to the `wait for' form of the
 * VHDL wait statement.
 */
static int draw_delay(vhdl_process *proc, ivl_statement_t stmt)
{
   std::cout << "draw_delay" << std::endl;
   return 0;
}

/*
 * A wait statement waits for a level change on a @(..) list of
 * signals.
 * TODO: This won't yet handle the posedge to rising_edge, etc.
 * mapping.
 */
static int draw_wait(vhdl_process *proc, ivl_statement_t stmt)
{
   int nevents = ivl_stmt_nevent(stmt);
   for (int i = 0; i < nevents; i++) {
      ivl_event_t event = ivl_stmt_events(stmt, i);

      if (ivl_event_nneg(event) != 0)
         error("Negative edge events not supported yet");
      if (ivl_event_npos(event) != 0)
         error("Positive edge events not supported yet");

      int nany = ivl_event_nany(event);
      for (int i = 0; i < nany; i++) {
         ivl_nexus_t nexus = ivl_event_any(event, i);

         int nptrs = ivl_nexus_ptrs(nexus);
         for (int j = 0; j < nptrs; j++) {
            ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, j);

            ivl_signal_t sig;
            if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
               const char *signame = ivl_signal_basename(sig);

               // Only add this signal to the sensitivity if it's part
               // of the containing architecture (i.e. it has already
               // been declared)
               if (proc->get_parent()->have_declared(signame))
                  proc->add_sensitivity(signame);
            }
            else {
               // Ignore all other types of nexus pointer
            }
         }
      }
   }

   ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
   draw_stmt(proc, sub_stmt);

   return 0;
}

/*
 * Generate VHDL statements for the given Verilog statement and
 * add them to the given VHDL process.
 */
int draw_stmt(vhdl_process *proc, ivl_statement_t stmt)
{
   switch (ivl_statement_type(stmt)) {
   case IVL_ST_STASK:
      return draw_stask(proc, stmt);
   case IVL_ST_BLOCK:
      return draw_block(proc, stmt);
   case IVL_ST_NOOP:
      return draw_noop(proc, stmt);
   case IVL_ST_ASSIGN_NB:
      return draw_nbassign(proc, stmt);
   case IVL_ST_DELAY:
      return draw_delay(proc, stmt);
   case IVL_ST_WAIT:
      return draw_wait(proc, stmt);
   default:
      error("No VHDL translation for statement at %s:%d (type = %d)",
            ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
            ivl_statement_type(stmt));
      return 1;
   }
}
<commit_msg>Catch case where NULL return wasn't detected<commit_after>/*
 *  VHDL code generation for statements.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cstring>
#include <cassert>
#include <sstream>

/*
 * Generate VHDL for the $display system task.
 * This is implemented using the functions in std.textio. Each
 * parameter is written to a line variable in the process and
 * then the line is written to the special variable `Output'
 * (which represents the console). Subsequent $displays will
 * use the same line variable.
 *
 * It's possible, although quite unlikely, that there will be
 * name collision with an existing variable called
 * `Verilog_Display_Line' -- do something about this?
 */
static int draw_stask_display(vhdl_process *proc, ivl_statement_t stmt)
{
   // Add the package requirement to the containing entity
   proc->get_parent()->get_parent()->requires_package("std.textio");

   const char *display_line = "Verilog_Display_Line";

   if (!proc->have_declared_var(display_line)) {
      vhdl_type *line_type = new vhdl_scalar_type("Line");
      vhdl_var_decl *line_var =
         new vhdl_var_decl(display_line, line_type);
      line_var->set_comment("For generating $display output");
      proc->add_decl(line_var);
   }

   // Write the data into the line
   int count = ivl_stmt_parm_count(stmt);
   for (int i = 0; i < count; i++) {
      // $display may have an empty parameter, in which case
      // the expression will be null
      // The behaviour here seems to be to output a space
      ivl_expr_t net = ivl_stmt_parm(stmt, i);
      vhdl_expr *e = NULL;
      if (net) {
         vhdl_expr *base = translate_expr(net);
         if (NULL == base)
            return 1;

         // Need to add a call to Type'Image for types not
         // supported by std.textio
         if (base->get_type()->get_name() != "String") {
            std::string name(base->get_type()->get_name());
            name += "'Image";

            vhdl_fcall *cast
               = new vhdl_fcall(name.c_str(), vhdl_scalar_type::string());
            cast->add_expr(base);
            e = cast;
         }
         else
            e = base;
      }
      else
         e = new vhdl_const_string(" ");

      vhdl_pcall_stmt *write = new vhdl_pcall_stmt("Write");
      vhdl_var_ref *ref =
         new vhdl_var_ref(display_line, vhdl_scalar_type::line());
      write->add_expr(ref);
      write->add_expr(e);

      proc->add_stmt(write);
   }

   // WriteLine(Output, Verilog_Display_Line)
   vhdl_pcall_stmt *write_line = new vhdl_pcall_stmt("WriteLine");
   vhdl_var_ref *output_ref =
      new vhdl_var_ref("std.textio.Output", new vhdl_scalar_type("File"));
   write_line->add_expr(output_ref);
   vhdl_var_ref *ref =
      new vhdl_var_ref(display_line, vhdl_scalar_type::line());
   write_line->add_expr(ref);
   proc->add_stmt(write_line);

   return 0;
}

/*
 * Generate VHDL for system tasks (like $display). Not all of
 * these are supported.
 */
static int draw_stask(vhdl_process *proc, ivl_statement_t stmt)
{
   const char *name = ivl_stmt_name(stmt);

   if (strcmp(name, "$display") == 0)
      return draw_stask_display(proc, stmt);
   else {
      error("No VHDL translation for system task %s", name);
      return 0;
   }
}

/*
 * Generate VHDL for a block of Verilog statements. This doesn't
 * actually do anything, other than recursively translate the
 * block's statements and add them to the process. This is OK as
 * `begin' and `end process' function like a Verilog block.
 */
static int draw_block(vhdl_process *proc, ivl_statement_t stmt)
{
   int count = ivl_stmt_block_count(stmt);
   for (int i = 0; i < count; i++) {
      if (draw_stmt(proc, ivl_stmt_block_stmt(stmt, i)) != 0)
         return 1;
   }
   return 0;
}

/*
 * A no-op statement. This corresponds to a `null' statement in
 * VHDL.
 */
static int draw_noop(vhdl_process *proc, ivl_statement_t stmt)
{
   proc->add_stmt(new vhdl_null_stmt());
   return 0;
}

/*
 * A non-blocking assignment inside a process. The semantics for
 * this are essentially the same as VHDL's non-blocking signal
 * assignment.
 */
static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt)
{
   int nlvals = ivl_stmt_lvals(stmt);
   if (nlvals != 1) {
      error("Can only have 1 lval at the moment (found %d)", nlvals);
      return 1;
   }

   ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
   ivl_signal_t sig;
   if ((sig = ivl_lval_sig(lval))) {
      const char *signame = ivl_signal_basename(sig);

      vhdl_decl *decl = proc->get_parent()->get_decl(signame);
      assert(decl);

      vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
      if (NULL == rhs_raw)
         return 1;
      vhdl_expr *rhs =  decl->get_type()->cast(rhs_raw);

      // The type here can be null as it is never actually needed
      vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL);

      proc->add_stmt(new vhdl_nbassign_stmt(lval_ref, rhs));
   }
   else {
      error("Only signals as lvals supported at the moment");
      return 1;
   }

   return 0;
}

/*
 * Delay statements are equivalent to the `wait for' form of the
 * VHDL wait statement.
 */
static int draw_delay(vhdl_process *proc, ivl_statement_t stmt)
{
   std::cout << "draw_delay" << std::endl;
   return 0;
}

/*
 * A wait statement waits for a level change on a @(..) list of
 * signals.
 * TODO: This won't yet handle the posedge to rising_edge, etc.
 * mapping.
 */
static int draw_wait(vhdl_process *proc, ivl_statement_t stmt)
{
   int nevents = ivl_stmt_nevent(stmt);
   for (int i = 0; i < nevents; i++) {
      ivl_event_t event = ivl_stmt_events(stmt, i);

      if (ivl_event_nneg(event) != 0)
         error("Negative edge events not supported yet");
      if (ivl_event_npos(event) != 0)
         error("Positive edge events not supported yet");

      int nany = ivl_event_nany(event);
      for (int i = 0; i < nany; i++) {
         ivl_nexus_t nexus = ivl_event_any(event, i);

         int nptrs = ivl_nexus_ptrs(nexus);
         for (int j = 0; j < nptrs; j++) {
            ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, j);

            ivl_signal_t sig;
            if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
               const char *signame = ivl_signal_basename(sig);

               // Only add this signal to the sensitivity if it's part
               // of the containing architecture (i.e. it has already
               // been declared)
               if (proc->get_parent()->have_declared(signame))
                  proc->add_sensitivity(signame);
            }
            else {
               // Ignore all other types of nexus pointer
            }
         }
      }
   }

   ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
   draw_stmt(proc, sub_stmt);

   return 0;
}

/*
 * Generate VHDL statements for the given Verilog statement and
 * add them to the given VHDL process.
 */
int draw_stmt(vhdl_process *proc, ivl_statement_t stmt)
{
   switch (ivl_statement_type(stmt)) {
   case IVL_ST_STASK:
      return draw_stask(proc, stmt);
   case IVL_ST_BLOCK:
      return draw_block(proc, stmt);
   case IVL_ST_NOOP:
      return draw_noop(proc, stmt);
   case IVL_ST_ASSIGN_NB:
      return draw_nbassign(proc, stmt);
   case IVL_ST_DELAY:
      return draw_delay(proc, stmt);
   case IVL_ST_WAIT:
      return draw_wait(proc, stmt);
   default:
      error("No VHDL translation for statement at %s:%d (type = %d)",
            ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
            ivl_statement_type(stmt));
      return 1;
   }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, 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.
 *
 *******************************************************************************/

#include <miopen/miopen.h>
#include <miopen/manage_ptr.hpp>
#include <miopen/fusion_plan.hpp>
#include <miopen/stringutils.hpp>
#include <miopen/env.hpp>

#include "get_handle.hpp"
#include "test.hpp"

#define WORKAROUND_ISSUE_763 1

MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_AMD_FUSED_WINOGRAD)
MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_GCN_ASM_KERNELS)
void BNAlgTest(std::vector<int> inputs,
               miopenBatchNormMode_t bnmode,
               std::string& pgm,
               std::string& krn,
               std::string& alg)
{
    MIOPEN_LOG_I("*********************************************************");
    auto&& handle = get_handle();
    miopen::TensorDescriptor inputTensor;
    miopen::TensorDescriptor scaleTensor;
    miopenFusionOpDescriptor_t bNormOp = nullptr;

    // input descriptor
    STATUS(miopenSet4dTensorDescriptor(
        &inputTensor, miopenFloat, inputs[0], inputs[1], inputs[2], inputs[3]));
    miopen::FusionPlanDescriptor fp(miopenVerticalFusion, inputTensor);

    miopenCreateOpBatchNormInference(&fp, &bNormOp, bnmode, &scaleTensor);

    pgm = fp.GetProgramName(handle);
    krn = fp.GetKernelName(handle);
    alg = fp.GetAlgorithmName(handle);
}

void ConvAlgTest(std::vector<int> inputs,
                 std::vector<int> conv_filter,
                 std::vector<int> conv_desc,
                 std::string& pgm,
                 std::string& krn,
                 std::string& alg)
{
    MIOPEN_LOG_I("*********************************************************");
    auto&& handle = get_handle();
    miopen::TensorDescriptor inputTensor;
    miopen::TensorDescriptor convFilter;
    miopenConvolutionDescriptor_t convDesc{};
    miopenFusionOpDescriptor_t convoOp;

    // input descriptor
    STATUS(miopenSet4dTensorDescriptor(
        &inputTensor, miopenFloat, inputs[0], inputs[1], inputs[2], inputs[3]));
    // convolution descriptor
    STATUS(miopenSet4dTensorDescriptor(&convFilter,
                                       miopenFloat,
                                       conv_filter[0], // outputs k
                                       conv_filter[1], // inputs c
                                       conv_filter[2], // kernel size
                                       conv_filter[3]));

    STATUS(miopenCreateConvolutionDescriptor(&convDesc));
    STATUS(miopenInitConvolutionDescriptor(convDesc,
                                           miopenConvolution,
                                           conv_desc[0],
                                           conv_desc[1],
                                           conv_desc[2],
                                           conv_desc[3],
                                           conv_desc[4],
                                           conv_desc[5]));

    miopen::FusionPlanDescriptor fp(miopenVerticalFusion, inputTensor);

    STATUS(miopenCreateOpConvForward(&fp, &convoOp, convDesc, &convFilter));
    pgm = fp.GetProgramName(handle);
    krn = fp.GetKernelName(handle);
    alg = fp.GetAlgorithmName(handle);

    // Cleanup
    miopenDestroyConvolutionDescriptor(convDesc);
}

int main()
{
    std::string pgm_name;
    std::string krn_name;
    std::string alg_name;

    bool skip_unsupported_alg = false;

#if WORKAROUND_ISSUE_763
    auto&& h       = get_handle();
    auto this_arch = h.GetDeviceName();
    if(this_arch.find("gfx10") != std::string::npos)
        skip_unsupported_alg = true;
#endif

    if(!miopen::IsDisabled(MIOPEN_DEBUG_AMD_FUSED_WINOGRAD{}) && !skip_unsupported_alg)
    {
        const auto name = get_handle().GetDeviceName();
        if(miopen::StartsWith(name, "gfx8"))
        {
            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 32, 8, 8}, {64, 32, 3, 3}, {1, 1, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // c is odd so winograd not supported and padding is zero
            ConvAlgTest(
                {100, 31, 8, 8}, {64, 31, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name != "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name != "miopenConvolutionWinogradBiasActiv");

            // c is less than 18 so winograd not supported and padding is zero
            ConvAlgTest(
                {100, 15, 8, 8}, {64, 15, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name != "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name != "miopenConvolutionWinogradBiasActiv");
        }
        else if(miopen::StartsWith(name, "gfx9") || miopen::StartsWith(name, "gfx10"))
        {
            std::string krn_name_ref = "miopenSp3AsmConv_v21_1_2_";
            if(miopen::StartsWith(name, "gfx9"))
            {
                krn_name_ref += "gfx9";
            }
            else // StartsWith(name, "gfx10")
            {
                krn_name_ref += "gfx10";
            }
            krn_name_ref += "_fp32_stride1";

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 32, 8, 8}, {64, 32, 3, 3}, {1, 1, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 31, 8, 8}, {64, 31, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 15, 8, 8}, {64, 15, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");
        }
    }
    // the asm kernel is the fastest for 1x1 and padding
    if(!miopen::IsDisabled(MIOPEN_DEBUG_GCN_ASM_KERNELS{}) && !skip_unsupported_alg)
    {
        ConvAlgTest(
            {100, 32, 8, 8}, {64, 32, 1, 1}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
        EXPECT(pgm_name == "conv1x1u_bias_activ.s");
        EXPECT(krn_name == "miopenGcnAsmConv1x1U");
        EXPECT(alg_name == "miopenConvolutionDirectBiasActivAsm");
    }

    // only the opencl kernels supports other odd sizes with padding zero
    for(auto idx : {5, 7, 9, 11})
    {
        ConvAlgTest(
            {100, 32, 8, 8}, {64, 32, idx, idx}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
        EXPECT(pgm_name == "MIOpenConvDirBatchNormActiv.cl");
        EXPECT(krn_name == "MIOpenConvUniBatchNormActiv");
        EXPECT(alg_name == "miopenConvolutionDirectBiasActiv");
    }

    BNAlgTest({100, 32, 8, 8}, miopenBNSpatial, pgm_name, krn_name, alg_name);
    EXPECT(pgm_name == "MIOpenBatchNormActivInfer.cl");
    EXPECT(krn_name == "MIOpenBatchNormActivInferSpatialEst");
    EXPECT(alg_name == "MIOpenBatchNormActivInferSpatialEst");

    BNAlgTest({100, 32, 8, 8}, miopenBNPerActivation, pgm_name, krn_name, alg_name);
    EXPECT(pgm_name == "MIOpenBatchNormActivInfer.cl");
    EXPECT(krn_name == "MIOpenBatchNormActivInferPerActEst");
    EXPECT(alg_name == "MIOpenBatchNormActivInferPerActEst");
}
<commit_msg>[tests] test_mdgraph: skip unsupported arch (#813)<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, 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.
 *
 *******************************************************************************/

#include <miopen/miopen.h>
#include <miopen/manage_ptr.hpp>
#include <miopen/fusion_plan.hpp>
#include <miopen/stringutils.hpp>
#include <miopen/env.hpp>

#include "get_handle.hpp"
#include "test.hpp"

MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_AMD_FUSED_WINOGRAD)
MIOPEN_DECLARE_ENV_VAR(MIOPEN_DEBUG_GCN_ASM_KERNELS)
void BNAlgTest(std::vector<int> inputs,
               miopenBatchNormMode_t bnmode,
               std::string& pgm,
               std::string& krn,
               std::string& alg)
{
    MIOPEN_LOG_I("*********************************************************");
    auto&& handle = get_handle();
    miopen::TensorDescriptor inputTensor;
    miopen::TensorDescriptor scaleTensor;
    miopenFusionOpDescriptor_t bNormOp = nullptr;

    // input descriptor
    STATUS(miopenSet4dTensorDescriptor(
        &inputTensor, miopenFloat, inputs[0], inputs[1], inputs[2], inputs[3]));
    miopen::FusionPlanDescriptor fp(miopenVerticalFusion, inputTensor);

    miopenCreateOpBatchNormInference(&fp, &bNormOp, bnmode, &scaleTensor);

    pgm = fp.GetProgramName(handle);
    krn = fp.GetKernelName(handle);
    alg = fp.GetAlgorithmName(handle);
}

void ConvAlgTest(std::vector<int> inputs,
                 std::vector<int> conv_filter,
                 std::vector<int> conv_desc,
                 std::string& pgm,
                 std::string& krn,
                 std::string& alg)
{
    MIOPEN_LOG_I("*********************************************************");
    auto&& handle = get_handle();
    miopen::TensorDescriptor inputTensor;
    miopen::TensorDescriptor convFilter;
    miopenConvolutionDescriptor_t convDesc{};
    miopenFusionOpDescriptor_t convoOp;

    // input descriptor
    STATUS(miopenSet4dTensorDescriptor(
        &inputTensor, miopenFloat, inputs[0], inputs[1], inputs[2], inputs[3]));
    // convolution descriptor
    STATUS(miopenSet4dTensorDescriptor(&convFilter,
                                       miopenFloat,
                                       conv_filter[0], // outputs k
                                       conv_filter[1], // inputs c
                                       conv_filter[2], // kernel size
                                       conv_filter[3]));

    STATUS(miopenCreateConvolutionDescriptor(&convDesc));
    STATUS(miopenInitConvolutionDescriptor(convDesc,
                                           miopenConvolution,
                                           conv_desc[0],
                                           conv_desc[1],
                                           conv_desc[2],
                                           conv_desc[3],
                                           conv_desc[4],
                                           conv_desc[5]));

    miopen::FusionPlanDescriptor fp(miopenVerticalFusion, inputTensor);

    STATUS(miopenCreateOpConvForward(&fp, &convoOp, convDesc, &convFilter));
    pgm = fp.GetProgramName(handle);
    krn = fp.GetKernelName(handle);
    alg = fp.GetAlgorithmName(handle);

    // Cleanup
    miopenDestroyConvolutionDescriptor(convDesc);
}

int main()
{
    std::string pgm_name;
    std::string krn_name;
    std::string alg_name;

    auto&& h = get_handle();

    auto this_arch = h.GetDeviceName();

    auto wino_supported_arch = {"gfx908", "gfx906", "gfx900", "gfx803"};

    bool is_wino_support = std::any_of(wino_supported_arch.begin(),
                                       wino_supported_arch.end(),
                                       [&](std::string arch) { return arch == this_arch; });

    if(!miopen::IsDisabled(MIOPEN_DEBUG_AMD_FUSED_WINOGRAD{}) && is_wino_support)
    {
        const auto name = get_handle().GetDeviceName();
        if(miopen::StartsWith(name, "gfx8"))
        {
            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 32, 8, 8}, {64, 32, 3, 3}, {1, 1, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // c is odd so winograd not supported and padding is zero
            ConvAlgTest(
                {100, 31, 8, 8}, {64, 31, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name != "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name != "miopenConvolutionWinogradBiasActiv");

            // c is less than 18 so winograd not supported and padding is zero
            ConvAlgTest(
                {100, 15, 8, 8}, {64, 15, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name != "miopenSp3AsmConvRxSU_CBA");
            EXPECT(alg_name != "miopenConvolutionWinogradBiasActiv");
        }
        else if(miopen::StartsWith(name, "gfx9") || miopen::StartsWith(name, "gfx10"))
        {
            std::string krn_name_ref = "miopenSp3AsmConv_v21_1_2_";
            if(miopen::StartsWith(name, "gfx9"))
            {
                krn_name_ref += "gfx9";
            }
            else // StartsWith(name, "gfx10")
            {
                krn_name_ref += "gfx10";
            }
            krn_name_ref += "_fp32_stride1";

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 32, 8, 8}, {64, 32, 3, 3}, {1, 1, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 31, 8, 8}, {64, 31, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");

            // Winograd because c, x and y satisfy criteria
            ConvAlgTest(
                {100, 15, 8, 8}, {64, 15, 3, 3}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
            EXPECT(krn_name == krn_name_ref);
            EXPECT(alg_name == "miopenConvolutionWinogradBiasActiv");
        }
    }

    auto asm_supported_arch = {"gfx908", "gfx906", "gfx900", "gfx803"};

    bool is_asm_support = std::any_of(asm_supported_arch.begin(),
                                      asm_supported_arch.end(),
                                      [&](std::string arch) { return arch == this_arch; });

    // the asm kernel is the fastest for 1x1 and padding
    if(!miopen::IsDisabled(MIOPEN_DEBUG_GCN_ASM_KERNELS{}) && is_asm_support)
    {
        ConvAlgTest(
            {100, 32, 8, 8}, {64, 32, 1, 1}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
        EXPECT(pgm_name == "conv1x1u_bias_activ.s");
        EXPECT(krn_name == "miopenGcnAsmConv1x1U");
        EXPECT(alg_name == "miopenConvolutionDirectBiasActivAsm");
    }

    // only the opencl kernels supports other odd sizes with padding zero
    for(auto idx : {5, 7, 9, 11})
    {
        ConvAlgTest(
            {100, 32, 8, 8}, {64, 32, idx, idx}, {0, 0, 1, 1, 1, 1}, pgm_name, krn_name, alg_name);
        EXPECT(pgm_name == "MIOpenConvDirBatchNormActiv.cl");
        EXPECT(krn_name == "MIOpenConvUniBatchNormActiv");
        EXPECT(alg_name == "miopenConvolutionDirectBiasActiv");
    }

    BNAlgTest({100, 32, 8, 8}, miopenBNSpatial, pgm_name, krn_name, alg_name);
    EXPECT(pgm_name == "MIOpenBatchNormActivInfer.cl");
    EXPECT(krn_name == "MIOpenBatchNormActivInferSpatialEst");
    EXPECT(alg_name == "MIOpenBatchNormActivInferSpatialEst");

    BNAlgTest({100, 32, 8, 8}, miopenBNPerActivation, pgm_name, krn_name, alg_name);
    EXPECT(pgm_name == "MIOpenBatchNormActivInfer.cl");
    EXPECT(krn_name == "MIOpenBatchNormActivInferPerActEst");
    EXPECT(alg_name == "MIOpenBatchNormActivInferPerActEst");
}
<|endoftext|>