<commit_before>/* Copyright (c) 2014 Quanta Research Cambridge, 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 <stdio.h>
#include "GeneratedTypes.h"
#include <python2.7/Python.h>

static PyObject *callbackFunction;
static PortalInternal erequest, eindication;
static PortalInternal dummy;

#define STUB \
{ \
    printf("[%s:%d]\n", __FUNCTION__, __LINE__); \
    exit(-1); \
}
static volatile unsigned int *dummyMAPCHANNELIND(struct PortalInternal *pint, unsigned int v)
{
    return &dummy.map_base[0];
}
static volatile unsigned int *dummyMAPCHANNELREQ(struct PortalInternal *pint, unsigned int v, unsigned int size)
{
    return &dummy.map_base[0];
}
static void dummySENDMSG(struct PortalInternal *pint, volatile unsigned int *buffer, unsigned int hdr, int sendFd)
{
}
static int dummyTRANSPORTINIT(struct PortalInternal *pint, void *param) STUB
static unsigned int dummyREADWORD(struct PortalInternal *pint, volatile unsigned int **addr) STUB
static void dummyWRITEWORD(struct PortalInternal *pint, volatile unsigned int **addr, unsigned int v) STUB
static void dummyWRITEFDWORD(struct PortalInternal *pint, volatile unsigned int **addr, unsigned int v) STUB
static int dummyRECVMSG(struct PortalInternal *pint, volatile unsigned int *buffer, int len, int *recvfd) STUB
static int dummyBUSYWAIT(struct PortalInternal *pint, unsigned int v, const char *str) STUB
static void dummyENABLEINT(struct PortalInternal *pint, int val) STUB
static int dummyEVENT(struct PortalInternal *pint) STUB
static int dummyNOTFULL(struct PortalInternal *pint, unsigned int v) STUB
PortalTransportFunctions callbackTransport = {
    dummyTRANSPORTINIT, dummyREADWORD, dummyWRITEWORD, dummyWRITEFDWORD,
    dummyMAPCHANNELIND, dummyMAPCHANNELREQ, dummySENDMSG, dummyRECVMSG,
    dummyBUSYWAIT, dummyENABLEINT, dummyEVENT, dummyNOTFULL};

static int heard_cb(struct PortalInternal *p,uint32_t v) {
    EchoIndicationJson_heard (&dummy, v);
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyEval_CallFunction(callbackFunction, "(s)", dummy.map_base, NULL);
    PyGILState_Release(gstate);
    return 0;
}
static int heard2_cb(struct PortalInternal *p,uint16_t a, uint16_t b) {
    EchoIndicationJson_heard2 (&dummy, a, b);
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyEval_CallFunction(callbackFunction, "(s)", dummy.map_base, NULL);
    PyGILState_Release(gstate);
    return 0;
}
static EchoIndicationCb EchoInd_cbTable = { portal_disconnect, heard_cb, heard2_cb};

extern "C" {
void set_callback(PyObject *param)
{
    Py_INCREF(param);
    callbackFunction = param;
    dummy.transport = &callbackTransport;
    dummy.map_base = (volatile unsigned int *)malloc(1000);
}

void *trequest()
{
    init_portal_internal(&erequest, IfcNames_EchoRequest, DEFAULT_TILE, NULL, NULL, NULL, NULL, EchoRequest_reqinfo);
//void init_portal_internal(PortalInternal *pint, int id, int tile, PORTAL_INDFUNC handler, void *cb, PortalTransportFunctions *transport, void *param, uint32_t reqinfo);
    return &erequest;
}
void *tindication()
{
    init_portal_internal(&eindication, IfcNames_EchoIndication, DEFAULT_TILE,
        (PORTAL_INDFUNC) EchoIndication_handleMessage, &EchoInd_cbTable, NULL, NULL, EchoIndication_reqinfo);
    return &eindication;
}
} // extern "C"
<commit_msg>added parent pointer<commit_after>/* Copyright (c) 2014 Quanta Research Cambridge, 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 <stdio.h>
#include "GeneratedTypes.h"
#include <python2.7/Python.h>

static PyObject *callbackFunction;
static PortalInternal erequest, eindication;
static PortalInternal dummy;

#define STUB \
{ \
    printf("[%s:%d]\n", __FUNCTION__, __LINE__); \
    exit(-1); \
}
static volatile unsigned int *dummyMAPCHANNELIND(struct PortalInternal *pint, unsigned int v)
{
    return &dummy.map_base[0];
}
static volatile unsigned int *dummyMAPCHANNELREQ(struct PortalInternal *pint, unsigned int v, unsigned int size)
{
    return &dummy.map_base[0];
}
static void dummySENDMSG(struct PortalInternal *pint, volatile unsigned int *buffer, unsigned int hdr, int sendFd)
{
}
static int dummyTRANSPORTINIT(struct PortalInternal *pint, void *param) STUB
static unsigned int dummyREADWORD(struct PortalInternal *pint, volatile unsigned int **addr) STUB
static void dummyWRITEWORD(struct PortalInternal *pint, volatile unsigned int **addr, unsigned int v) STUB
static void dummyWRITEFDWORD(struct PortalInternal *pint, volatile unsigned int **addr, unsigned int v) STUB
static int dummyRECVMSG(struct PortalInternal *pint, volatile unsigned int *buffer, int len, int *recvfd) STUB
static int dummyBUSYWAIT(struct PortalInternal *pint, unsigned int v, const char *str) STUB
static void dummyENABLEINT(struct PortalInternal *pint, int val) STUB
static int dummyEVENT(struct PortalInternal *pint) STUB
static int dummyNOTFULL(struct PortalInternal *pint, unsigned int v) STUB
PortalTransportFunctions callbackTransport = {
    dummyTRANSPORTINIT, dummyREADWORD, dummyWRITEWORD, dummyWRITEFDWORD,
    dummyMAPCHANNELIND, dummyMAPCHANNELREQ, dummySENDMSG, dummyRECVMSG,
    dummyBUSYWAIT, dummyENABLEINT, dummyEVENT, dummyNOTFULL};

static int heard_cb(struct PortalInternal *p,uint32_t v) {
    EchoIndicationJson_heard (&dummy, v);
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyEval_CallFunction(callbackFunction, "(s)", dummy.map_base, NULL);
    PyGILState_Release(gstate);
    return 0;
}
static int heard2_cb(struct PortalInternal *p,uint16_t a, uint16_t b) {
    EchoIndicationJson_heard2 (&dummy, a, b);
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyEval_CallFunction(callbackFunction, "(s)", dummy.map_base, NULL);
    PyGILState_Release(gstate);
    return 0;
}
static EchoIndicationCb EchoInd_cbTable = { portal_disconnect, heard_cb, heard2_cb};

extern "C" {
void set_callback(PyObject *param)
{
    Py_INCREF(param);
    callbackFunction = param;
    dummy.transport = &callbackTransport;
    dummy.map_base = (volatile unsigned int *)malloc(1000);
}

void *trequest()
{
  void *parent = NULL;
  init_portal_internal(&erequest, IfcNames_EchoRequestS2H, DEFAULT_TILE, NULL, NULL, NULL, NULL, parent, EchoRequest_reqinfo);
//void init_portal_internal(PortalInternal *pint, int id, int tile, PORTAL_INDFUNC handler, void *cb, PortalTransportFunctions *transport, void *param, uint32_t reqinfo);
    return &erequest;
}
void *tindication()
{
  void *parent = NULL;
    init_portal_internal(&eindication, IfcNames_EchoIndicationH2S, DEFAULT_TILE,
			 (PORTAL_INDFUNC) EchoIndication_handleMessage, &EchoInd_cbTable, NULL, NULL, parent, EchoIndication_reqinfo);
    return &eindication;
}
} // extern "C"
<|endoftext|>


<commit_before>#include "mcp23017.hpp"

#include <mbed.h>
#include <logger.hpp>

// Declaration for the pointer to the global object
shared_ptr<MCP23017> MCP23017::instance;

shared_ptr<MCP23017>& MCP23017::Instance() {
    if (instance.get() == nullptr) instance.reset(new MCP23017);

    return instance;
}

bool MCP23017::Init() {
    auto instance = Instance();

    instance->_i2c.frequency(400000);
    reset();
    config(0x00FF, 0x0000, 0x0000);

    LOG(OK, "MCP23017 initialized");

    return true;
}

/*-----------------------------------------------------------------------------
 * reset
 * Set configuration (IOCON) and direction(IODIR) registers to initial state
 */
void MCP23017::reset() {
    // Set the shadow registers to power-on state
    inputOutputMask(0xFFFF);

    // set all other registers to zero (last of 10 registers is OLAT)
    for (int reg_addr = 2; reg_addr <= OLAT; reg_addr += 2)
        writeRegister(reg_addr, (unsigned short)0x0000);

    instance->shadow_GPIO = 0;
    instance->shadow_GPPU = 0;
    instance->shadow_IPOL = 0;
}

/*-----------------------------------------------------------------------------
 * writeRegister
 * write a byte
 */
void MCP23017::writeRegister(int regAddress, unsigned char data) {
    char buffer[2];
    buffer[0] = regAddress;
    buffer[1] = data;

    instance->_i2c.write(instance->_i2cAddress, buffer, 2);
}

/*----------------------------------------------------------------------------
 * write Register
 * write two bytes
 */
void MCP23017::writeRegister(int regAddress, unsigned short data) {
    char buffer[3];
    buffer[0] = regAddress;
    buffer[1] = data & 0xFF;
    buffer[2] = (data >> 8) & 0xFF;

    instance->_i2c.write(instance->_i2cAddress, buffer, 3);
}

/*-----------------------------------------------------------------------------
 * readRegister
 */
int MCP23017::readRegister(int regAddress) {
    char buffer[2];
    instance->_i2c.write(regAddress);
    instance->_i2c.read(instance->_i2cAddress, buffer, 2);

    return (int)(buffer[0] | (buffer[1] << 8));
}

/*-----------------------------------------------------------------------------
 * write_bit
 * Write a 1/0 to a single bit of the 16-bit port
 */
void MCP23017::write_bit(int value, int bit_number) {
    if (value == 0) {
        instance->shadow_GPIO &= ~(1 << bit_number);
    } else {
        instance->shadow_GPIO |= 1 << bit_number;
    }

    digitalWordWrite(instance->shadow_GPIO);
}

/*-----------------------------------------------------------------------------
 * Write a combination of bits to the 16-bit port
 */
void MCP23017::write_mask(unsigned short data, unsigned short mask) {
    instance->shadow_GPIO = (instance->shadow_GPIO & ~mask) | data;
    digitalWordWrite(instance->shadow_GPIO);
}

/*-----------------------------------------------------------------------------
 * read_bit
 * Read a single bit from the 16-bit port
 */
int MCP23017::read_bit(int bit_number) {
    instance->shadow_GPIO = digitalWordRead();

    LOG(INF2,
        "Read an I/O pin bit:"
        "    Bit:\t%u\r\n"
        "    State:\t%s",
        bit_number,
        ((instance->shadow_GPIO >> bit_number) & 0x0001) ? "ON" : "OFF");

    return ((instance->shadow_GPIO >> bit_number) & 0x0001);
}

/*-----------------------------------------------------------------------------
 * read_mask
 */
int MCP23017::read_mask(unsigned short mask) {
    return readRegister(GPIO) & mask;
}

/*-----------------------------------------------------------------------------
 * Config
 * set direction and pull-up registers
 */
void MCP23017::config(unsigned short dir_config, unsigned short pullup_config,
                      unsigned short polarity_config) {
    inputOutputMask(dir_config);
    internalPullupMask(pullup_config);
    inputPolarityMask(polarity_config);

    LOG(INIT,
        "IO Expander Configuration:\r\n"
        "    IODIR:\t0x%04X\r\n"
        "    GPPU:\t0x%04X\r\n"
        "    IPOL:\t0x%04X",
        instance->shadow_IODIR, instance->shadow_GPPU, instance->shadow_IPOL);
}

/*-----------------------------------------------------------------------------
 * pinMode
 */
void MCP23017::pinMode(int pin, int mode) {
    if (DIR_INPUT) {
        instance->shadow_IODIR |= 1 << pin;
    } else {
        instance->shadow_IODIR &= ~(1 << pin);
    }

    inputOutputMask(instance->shadow_IODIR);
}

/*-----------------------------------------------------------------------------
 * digitalRead
 */
int MCP23017::digitalRead(int pin) {
    instance->shadow_GPIO = readRegister(GPIO);
    return ((instance->shadow_GPIO & (1 << pin)) ? 1 : 0);
}

/*-----------------------------------------------------------------------------
 * digitalWrite
 */
void MCP23017::digitalWrite(int pin, int val) {
    // If this pin is an INPUT pin, a write here will
    // enable the internal pullup
    // otherwise, it will set the OUTPUT voltage
    // as appropriate.
    bool isOutput = !(instance->shadow_IODIR & 1 << pin);

    if (isOutput) {
        // This is an output pin so just write the value
        if (val)
            instance->shadow_GPIO |= 1 << pin;
        else
            instance->shadow_GPIO &= ~(1 << pin);

        digitalWordWrite(instance->shadow_GPIO);
    } else {
        // This is an input pin, so we need to enable the pullup
        if (val) {
            instance->shadow_GPPU |= 1 << pin;
        } else {
            instance->shadow_GPPU &= ~(1 << pin);
        }

        internalPullupMask(instance->shadow_GPPU);
    }
}

/*-----------------------------------------------------------------------------
 * digitalWordRead
 */
unsigned short MCP23017::digitalWordRead() {
    instance->shadow_GPIO = readRegister(GPIO);
    return instance->shadow_GPIO;
}

/*-----------------------------------------------------------------------------
 * digitalWordWrite
 */
void MCP23017::digitalWordWrite(unsigned short w) {
    instance->shadow_GPIO = w;
    writeRegister(GPIO, w);
}

/*-----------------------------------------------------------------------------
 * inputPolarityMask
 */
void MCP23017::inputPolarityMask(unsigned short mask) {
    instance->shadow_IPOL = mask;
    writeRegister(IPOL, (unsigned short)instance->shadow_IPOL);
}

/*-----------------------------------------------------------------------------
 * inputoutputMask
 */
void MCP23017::inputOutputMask(unsigned short mask) {
    instance->shadow_IODIR = mask;
    writeRegister(IODIR, (unsigned short)instance->shadow_IODIR);
}

/*-----------------------------------------------------------------------------
 * internalPullupMask
 */
void MCP23017::internalPullupMask(unsigned short mask) {
    instance->shadow_GPPU = mask;
    writeRegister(GPPU, (unsigned short)instance->shadow_GPPU);
}
<commit_msg>fixing startup log message<commit_after>#include "mcp23017.hpp"

#include <mbed.h>
#include <logger.hpp>

// Declaration for the pointer to the global object
shared_ptr<MCP23017> MCP23017::instance;

shared_ptr<MCP23017>& MCP23017::Instance() {
    if (instance.get() == nullptr) instance.reset(new MCP23017);

    return instance;
}

bool MCP23017::Init() {
    auto instance = Instance();

    instance->_i2c.frequency(400000);
    reset();
    config(0x00FF, 0x0000, 0x0000);

    LOG(OK, "MCP23017 initialized");

    return true;
}

/*-----------------------------------------------------------------------------
 * reset
 * Set configuration (IOCON) and direction(IODIR) registers to initial state
 */
void MCP23017::reset() {
    // Set the shadow registers to power-on state
    inputOutputMask(0xFFFF);

    // set all other registers to zero (last of 10 registers is OLAT)
    for (int reg_addr = 2; reg_addr <= OLAT; reg_addr += 2)
        writeRegister(reg_addr, (unsigned short)0x0000);

    instance->shadow_GPIO = 0;
    instance->shadow_GPPU = 0;
    instance->shadow_IPOL = 0;
}

/*-----------------------------------------------------------------------------
 * writeRegister
 * write a byte
 */
void MCP23017::writeRegister(int regAddress, unsigned char data) {
    char buffer[2];
    buffer[0] = regAddress;
    buffer[1] = data;

    instance->_i2c.write(instance->_i2cAddress, buffer, 2);
}

/*----------------------------------------------------------------------------
 * write Register
 * write two bytes
 */
void MCP23017::writeRegister(int regAddress, unsigned short data) {
    char buffer[3];
    buffer[0] = regAddress;
    buffer[1] = data & 0xFF;
    buffer[2] = (data >> 8) & 0xFF;

    instance->_i2c.write(instance->_i2cAddress, buffer, 3);
}

/*-----------------------------------------------------------------------------
 * readRegister
 */
int MCP23017::readRegister(int regAddress) {
    char buffer[2];
    instance->_i2c.write(regAddress);
    instance->_i2c.read(instance->_i2cAddress, buffer, 2);

    return (int)(buffer[0] | (buffer[1] << 8));
}

/*-----------------------------------------------------------------------------
 * write_bit
 * Write a 1/0 to a single bit of the 16-bit port
 */
void MCP23017::write_bit(int value, int bit_number) {
    if (value == 0) {
        instance->shadow_GPIO &= ~(1 << bit_number);
    } else {
        instance->shadow_GPIO |= 1 << bit_number;
    }

    digitalWordWrite(instance->shadow_GPIO);
}

/*-----------------------------------------------------------------------------
 * Write a combination of bits to the 16-bit port
 */
void MCP23017::write_mask(unsigned short data, unsigned short mask) {
    instance->shadow_GPIO = (instance->shadow_GPIO & ~mask) | data;
    digitalWordWrite(instance->shadow_GPIO);
}

/*-----------------------------------------------------------------------------
 * read_bit
 * Read a single bit from the 16-bit port
 */
int MCP23017::read_bit(int bit_number) {
    instance->shadow_GPIO = digitalWordRead();

    LOG(INF2,
        "Read an I/O pin bit:"
        "    Bit:\t%u\r\n"
        "    State:\t%s",
        bit_number,
        ((instance->shadow_GPIO >> bit_number) & 0x0001) ? "ON" : "OFF");

    return ((instance->shadow_GPIO >> bit_number) & 0x0001);
}

/*-----------------------------------------------------------------------------
 * read_mask
 */
int MCP23017::read_mask(unsigned short mask) {
    return readRegister(GPIO) & mask;
}

/*-----------------------------------------------------------------------------
 * Config
 * set direction and pull-up registers
 */
void MCP23017::config(unsigned short dir_config, unsigned short pullup_config,
                      unsigned short polarity_config) {
    inputOutputMask(dir_config);
    internalPullupMask(pullup_config);
    inputPolarityMask(polarity_config);

    LOG(INF2,
        "IO Expander Configuration:\r\n"
        "    IODIR:\t0x%04X\r\n"
        "    GPPU:\t0x%04X\r\n"
        "    IPOL:\t0x%04X",
        instance->shadow_IODIR, instance->shadow_GPPU, instance->shadow_IPOL);
}

/*-----------------------------------------------------------------------------
 * pinMode
 */
void MCP23017::pinMode(int pin, int mode) {
    if (DIR_INPUT) {
        instance->shadow_IODIR |= 1 << pin;
    } else {
        instance->shadow_IODIR &= ~(1 << pin);
    }

    inputOutputMask(instance->shadow_IODIR);
}

/*-----------------------------------------------------------------------------
 * digitalRead
 */
int MCP23017::digitalRead(int pin) {
    instance->shadow_GPIO = readRegister(GPIO);
    return ((instance->shadow_GPIO & (1 << pin)) ? 1 : 0);
}

/*-----------------------------------------------------------------------------
 * digitalWrite
 */
void MCP23017::digitalWrite(int pin, int val) {
    // If this pin is an INPUT pin, a write here will
    // enable the internal pullup
    // otherwise, it will set the OUTPUT voltage
    // as appropriate.
    bool isOutput = !(instance->shadow_IODIR & 1 << pin);

    if (isOutput) {
        // This is an output pin so just write the value
        if (val)
            instance->shadow_GPIO |= 1 << pin;
        else
            instance->shadow_GPIO &= ~(1 << pin);

        digitalWordWrite(instance->shadow_GPIO);
    } else {
        // This is an input pin, so we need to enable the pullup
        if (val) {
            instance->shadow_GPPU |= 1 << pin;
        } else {
            instance->shadow_GPPU &= ~(1 << pin);
        }

        internalPullupMask(instance->shadow_GPPU);
    }
}

/*-----------------------------------------------------------------------------
 * digitalWordRead
 */
unsigned short MCP23017::digitalWordRead() {
    instance->shadow_GPIO = readRegister(GPIO);
    return instance->shadow_GPIO;
}

/*-----------------------------------------------------------------------------
 * digitalWordWrite
 */
void MCP23017::digitalWordWrite(unsigned short w) {
    instance->shadow_GPIO = w;
    writeRegister(GPIO, w);
}

/*-----------------------------------------------------------------------------
 * inputPolarityMask
 */
void MCP23017::inputPolarityMask(unsigned short mask) {
    instance->shadow_IPOL = mask;
    writeRegister(IPOL, (unsigned short)instance->shadow_IPOL);
}

/*-----------------------------------------------------------------------------
 * inputoutputMask
 */
void MCP23017::inputOutputMask(unsigned short mask) {
    instance->shadow_IODIR = mask;
    writeRegister(IODIR, (unsigned short)instance->shadow_IODIR);
}

/*-----------------------------------------------------------------------------
 * internalPullupMask
 */
void MCP23017::internalPullupMask(unsigned short mask) {
    instance->shadow_GPPU = mask;
    writeRegister(GPPU, (unsigned short)instance->shadow_GPPU);
}
<|endoftext|>


<commit_before>#ifndef COMMAND_HPP
#define COMMAND_HPP

#include <iostream>
#include <string>
#include <assert.h>

namespace fs {

/**
 * @brief command from client
 */
class Command
{
public:

    Command() = delete;

    Command(const char* msg, std::size_t len)
    {
        assert(msg);
        assert(len > 2);    //at least "\r\n"

        parse_and_init(msg);
    }

    const std::string& code()const
    {
        return code_;
    }

    const std::string& argument()const
    {
        return argt_;
    }

private:
    std::string code_;
    std::string argt_;

    void parse_and_init(const char* msg)
    {
        auto ch = msg;
        for(;       *ch != ' ';     ++ch)   code_.push_back(*ch);
        for(++ch;   *ch != '\r';    ++ch)   argt_.push_back(*ch);
    }
};

inline std::ostream&
operator <<(std::ostream& os, const Command& c)
{
    os << "[" << c.code()       << "]"
       << "[" << c.argument()   << "]";
    return os;
}
}//namespace

#endif // COMMAND_HPP

//! @test
//!
//#include <iostream>
//#include "command.hpp"
//int main()
//{
//    fs::Command cmd{"SYST ba1234\r\n",13};
//    std::cout << cmd;
//    return 0;
//}
//! @output
//[SYST][ba1234]
<commit_msg>fix parsing bug added operator == != 	modified:   ftp/command.hpp<commit_after>#ifndef COMMAND_HPP
#define COMMAND_HPP

#include <iostream>
#include <string>
#include <assert.h>

namespace fs {

/**
 * @brief command from client
 */
class Command
{
public:

    Command() = delete;

    Command(const char* msg, std::size_t len):
        code_{},argt_{}
    {
        len -= 2;   //remove "\r\n"

        unsigned idx=0;
        for(    ; idx!=len && !std::isspace(msg[idx]); ++idx)
            code_.push_back(msg[idx]);

        if(idx<len)
            for(++idx;  idx!=len;   ++idx)  argt_.push_back(msg[idx]);
    }

    const std::string& code()const
    {
        return code_;
    }

    const std::string& argument()const
    {
        return argt_;
    }

private:
    std::string code_;
    std::string argt_;
};

inline bool operator !=(const Command& lhs, const std::string& rhs)
{
    return lhs.code() != rhs;
}

inline bool operator !=(const std::string& lhs, const Command& rhs)
{
    return lhs != rhs.code();
}

inline bool operator ==(const Command& lhs, const std::string& rhs)
{
    return lhs.code() == rhs;
}

inline bool operator ==(const std::string& lhs, const Command& rhs)
{
    return lhs == rhs.code();
}

inline std::ostream&
operator <<(std::ostream& os, const Command& c)
{
    os << "[" << c.code()       << "]"
       << "[" << c.argument()   << "]";
    return os;
}
}//namespace

#endif // COMMAND_HPP

//! @test
//!
//#include <iostream>
//#include "command.hpp"
//int main()
//{
//    fs::Command cmd{"SYST ba1234\r\n",13};
//    std::cout << cmd;
//    return 0;
//}
//! @output
//[SYST][ba1234]
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2011-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : defines range generator
// ***************************************************************************

#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER

// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/size.hpp>

#include <boost/test/data/monomorphic/generate.hpp>

#include <boost/test/utils/named_params.hpp>

// Boost
#include <boost/optional.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_unsigned.hpp>

// STL
#include <limits>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {

// ************************************************************************** //
// **************             monomorphic::xrange_t            ************** //
// ************************************************************************** //

template<typename SampleType, typename StepType=SampleType>
class xrange_t {
public:
    typedef SampleType data_type;

    xrange_t( SampleType const& begin, StepType const& step, data::size_t size )
    : m_curr( begin )
    , m_step( step )
    , m_size( size )
    {}

    // Generator interface
    data::size_t    capacity() const { return m_size; }
    SampleType      next()
    {
        BOOST_TEST_DS_ASSERT( m_size != 0, "No more elements in range" );

        SampleType res = m_curr;

        m_curr += m_step;
        --m_size;

        return res;
    }
private:
    // Data members
    SampleType      m_curr;
    StepType        m_step;
    data::size_t    m_size;
};

//____________________________________________________________________________//

namespace {
nfp::keyword<struct begin_t >   begin;
nfp::keyword<struct end_t >     end;
nfp::keyword<struct step_t >    step;
}

//____________________________________________________________________________//

namespace ds_detail {

template<typename SampleType, typename StepType=SampleType>
struct make_xrange {
    static StepType    abs( StepType s, mpl::true_* )   { return s; }
    static StepType    abs( StepType s, mpl::false_* )  { return std::abs(s); }

    typedef xrange_t<SampleType, StepType> range_gen;

    template<typename Params>
    static generated_by<range_gen>
    _( Params const& params )
    {
        SampleType           begin_val  = params.has( monomorphic::begin )  ? params[monomorphic::begin] : SampleType();
        optional<SampleType> end_val    = params.has( monomorphic::end )    ? params[monomorphic::end]   : optional<SampleType>();
        StepType             step_val   = params.has( monomorphic::step )   ? params[monomorphic::step]  : 1;

        BOOST_TEST_DS_ASSERT( step_val != 0, "Range step can't be zero" );

        data::size_t size;
        if( !end_val.is_initialized() )
            size = BOOST_TEST_DS_INFINITE_SIZE;
        else {
            BOOST_TEST_DS_ASSERT( (step_val < 0) ^ (begin_val < *end_val), "Invalid step direction" );

            SampleType  abs_distance    = step_val < 0 ? begin_val - *end_val : *end_val-begin_val;
            StepType    abs_step        = make_xrange::abs(step_val, (boost::is_unsigned<StepType>::type*)0 );
            std::size_t s = static_cast<std::size_t>(abs_distance/abs_step);

            if( static_cast<SampleType>(s*abs_step) < abs_distance )
                s++;

            size = s;
        }

        return generated_by<range_gen>( range_gen( begin_val, step_val, size ) );
    }
};

} // namespace ds_detail
} // namespace monomorphic

//____________________________________________________________________________//

template<typename SampleType, typename Params>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( Params const& params )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::_( params );
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& end_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::_( monomorphic::end=end_val );
}

//____________________________________________________________________________//

template<typename SampleType, typename Params>
inline typename enable_if_c<nfp::is_named_params<Params>::value,monomorphic::generated_by<monomorphic::xrange_t<SampleType> > >::type
xrange( SampleType const& end_val, Params const& params )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::
            _(( params, monomorphic::end=end_val ));
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& begin_val, SampleType const& end_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::
            _(( monomorphic::begin=begin_val, monomorphic::end=end_val ));
}

//____________________________________________________________________________//

template<typename SampleType,typename StepType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType,StepType>::
            _(( monomorphic::begin=begin_val, monomorphic::end=end_val, monomorphic::step=step_val ));
}

//____________________________________________________________________________//

} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
<commit_msg>moved keywords<commit_after>//  (C) Copyright Gennadiy Rozental 2011-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : defines range generator
// ***************************************************************************

#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER

// Boost.Test
#include <boost/test/data/config.hpp>

#include <boost/test/data/monomorphic/generators/keywords.hpp>
#include <boost/test/data/monomorphic/generate.hpp>

// Boost
#include <boost/optional.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_unsigned.hpp>

// STL
#include <limits>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {

// ************************************************************************** //
// **************             monomorphic::xrange_t            ************** //
// ************************************************************************** //

template<typename SampleType, typename StepType=SampleType>
class xrange_t {
public:
    typedef SampleType data_type;

    xrange_t( SampleType const& begin, StepType const& step, data::size_t size )
    : m_curr( begin )
    , m_step( step )
    , m_size( size )
    {}

    // Generator interface
    data::size_t    capacity() const { return m_size; }
    SampleType      next()
    {
        BOOST_TEST_DS_ASSERT( m_size != 0, "No more elements in range" );

        SampleType res = m_curr;

        m_curr += m_step;
        --m_size;

        return res;
    }
private:
    // Data members
    SampleType      m_curr;
    StepType        m_step;
    data::size_t    m_size;
};

//____________________________________________________________________________//

namespace ds_detail {

template<typename SampleType, typename StepType=SampleType>
struct make_xrange {
    static StepType    abs( StepType s, mpl::true_* )   { return s; }
    static StepType    abs( StepType s, mpl::false_* )  { return std::abs(s); }

    typedef xrange_t<SampleType, StepType> range_gen;

    template<typename Params>
    static generated_by<range_gen>
    _( Params const& params )
    {
        SampleType           begin_val  = params.has( data::begin )  ? params[data::begin] : SampleType();
        optional<SampleType> end_val    = params.has( data::end )    ? params[data::end]   : optional<SampleType>();
        StepType             step_val   = params.has( data::step )   ? params[data::step]  : 1;

        BOOST_TEST_DS_ASSERT( step_val != 0, "Range step can't be zero" );

        data::size_t size;
        if( !end_val.is_initialized() )
            size = BOOST_TEST_DS_INFINITE_SIZE;
        else {
            BOOST_TEST_DS_ASSERT( (step_val < 0) ^ (begin_val < *end_val), "Invalid step direction" );

            SampleType  abs_distance    = step_val < 0 ? begin_val - *end_val : *end_val-begin_val;
            StepType    abs_step        = make_xrange::abs(step_val, (boost::is_unsigned<StepType>::type*)0 );
            std::size_t s = static_cast<std::size_t>(abs_distance/abs_step);

            if( static_cast<SampleType>(s*abs_step) < abs_distance )
                s++;

            size = s;
        }

        return generated_by<range_gen>( range_gen( begin_val, step_val, size ) );
    }
};

} // namespace ds_detail
} // namespace monomorphic

//____________________________________________________________________________//

template<typename SampleType, typename Params>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( Params const& params )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::_( params );
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& end_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::_( data::end=end_val );
}

//____________________________________________________________________________//

template<typename SampleType, typename Params>
inline typename enable_if_c<nfp::is_named_params<Params>::value,monomorphic::generated_by<monomorphic::xrange_t<SampleType> > >::type
xrange( SampleType const& end_val, Params const& params )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::
            _(( params, data::end=end_val ));
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& begin_val, SampleType const& end_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType>::
            _(( data::begin=begin_val, data::end=end_val ));
}

//____________________________________________________________________________//

template<typename SampleType,typename StepType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType> >
xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val )
{
    return monomorphic::ds_detail::make_xrange<SampleType,StepType>::
            _(( data::begin=begin_val, data::end=end_val, data::step=step_val ));
}

//____________________________________________________________________________//

} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// appleseed.foundation headers.
#include "foundation/image/analysis.h"
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/pixel.h"
#include "foundation/image/tile.h"
#include "foundation/math/fp.h"
#include "foundation/utility/test.h"

using namespace foundation;

TEST_SUITE(Foundation_Image_Analysis)
{
    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithZeroes_ReturnsZero)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(0.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_EQ(0.0, average_luminance);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithOnes_ReturnsOne)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(1.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_FEQ_EPS(1.0, average_luminance, 1.0e-6);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithMinusOnes_ReturnsZero)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(-1.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_EQ(0.0, average_luminance);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithOnesAndOnePixelSetToSNaN_ReturnsOne)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(1.0f));
        image.tile(0, 0).set_pixel(0, 0, Color4f(FP<float>::snan()));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_FEQ_EPS(1.0, average_luminance, 1.0e-6);
    }

    TEST_CASE(ComputeRMSDeviation_GivenBothImagesFilledWithZeroes_ReturnsZero)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(0.0f));
        image2.clear(Color4f(0.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_EQ(0.0, rmsd);
    }

    TEST_CASE(ComputeRMSDeviation_GivenBothImagesFilledWithOnes_ReturnsZero)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(1.0f));
        image2.clear(Color4f(1.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_EQ(0.0, rmsd);
    }

    TEST_CASE(ComputeRMSDeviation_GivenOneImageFilledWithZeroesAndOneImageFilledWithOnes_ReturnsOne)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(0.0f));
        image2.clear(Color4f(1.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_FEQ(1.0, rmsd);
    }
}
<commit_msg>improved a unit test.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// appleseed.foundation headers.
#include "foundation/image/analysis.h"
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/pixel.h"
#include "foundation/image/tile.h"
#include "foundation/math/fp.h"
#include "foundation/utility/test.h"

using namespace foundation;

TEST_SUITE(Foundation_Image_Analysis)
{
    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithZeroes_ReturnsZero)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(0.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_EQ(0.0, average_luminance);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithOnes_ReturnsOne)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(1.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_FEQ_EPS(1.0, average_luminance, 1.0e-6);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithMinusOnes_ReturnsZero)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(-1.0f));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_EQ(0.0, average_luminance);
    }

    TEST_CASE(ComputeAverageLuminance_GivenImageFilledWithOnesAndOnePixelSetToSNaN_ReturnsOne)
    {
        Image image(4, 4, 2, 2, 4, PixelFormatFloat);
        image.clear(Color4f(1.0f));
        image.tile(0, 0).set_pixel(1, 1, Color4f(FP<float>::snan()));

        const double average_luminance = compute_average_luminance(image);

        EXPECT_FEQ_EPS(1.0, average_luminance, 1.0e-6);
    }

    TEST_CASE(ComputeRMSDeviation_GivenBothImagesFilledWithZeroes_ReturnsZero)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(0.0f));
        image2.clear(Color4f(0.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_EQ(0.0, rmsd);
    }

    TEST_CASE(ComputeRMSDeviation_GivenBothImagesFilledWithOnes_ReturnsZero)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(1.0f));
        image2.clear(Color4f(1.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_EQ(0.0, rmsd);
    }

    TEST_CASE(ComputeRMSDeviation_GivenOneImageFilledWithZeroesAndOneImageFilledWithOnes_ReturnsOne)
    {
        Image image1(4, 4, 2, 2, 4, PixelFormatFloat);
        Image image2(4, 4, 2, 2, 4, PixelFormatFloat);

        image1.clear(Color4f(0.0f));
        image2.clear(Color4f(1.0f));

        const double rmsd = compute_rms_deviation(image1, image2);

        EXPECT_FEQ(1.0, rmsd);
    }
}
<|endoftext|>


<commit_before>/*
* Vulkan Example - Animated gears using multiple uniform buffers
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#include "vulkangear.h"
#include "vulkanexamplebase.h"

class VulkanExample : public VulkanExampleBase
{
public:
	struct {
		vk::PipelineVertexInputStateCreateInfo inputState;
		std::vector<vk::VertexInputBindingDescription> bindingDescriptions;
		std::vector<vk::VertexInputAttributeDescription> attributeDescriptions;
	} vertices;

	struct {
		vk::Pipeline solid;
	} pipelines;

	std::vector<VulkanGear*> gears;

	vk::PipelineLayout pipelineLayout;
	vk::DescriptorSetLayout descriptorSetLayout;

	VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
	{
		zoom = -16.0f;
		rotation = glm::vec3(-23.75, 41.25, 21.0);
		timerSpeed *= 0.25f;
		title = "Vulkan Example - Gears";
	}

	~VulkanExample()
	{
		// Clean up used Vulkan resources
		// Note : Inherited destructor cleans up resources stored in base class
		device.destroyPipeline(pipelines.solid);

		device.destroyPipelineLayout(pipelineLayout);
		device.destroyDescriptorSetLayout(descriptorSetLayout);

		for (auto& gear : gears)
		{
			delete(gear);
		}
	}

	void buildCommandBuffers()
	{
		vk::CommandBufferBeginInfo cmdBufInfo;

		vk::ClearValue clearValues[2];
		clearValues[0].color = defaultClearColor;
		clearValues[1].depthStencil = { 1.0f, 0 };

		vk::RenderPassBeginInfo renderPassBeginInfo;
		renderPassBeginInfo.renderPass = renderPass;
		renderPassBeginInfo.renderArea.offset.x = 0;
		renderPassBeginInfo.renderArea.offset.y = 0;
		renderPassBeginInfo.renderArea.extent.width = width;
		renderPassBeginInfo.renderArea.extent.height = height;
		renderPassBeginInfo.clearValueCount = 2;
		renderPassBeginInfo.pClearValues = clearValues;

		for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
		{
			// Set target frame buffer
			renderPassBeginInfo.framebuffer = frameBuffers[i];

			drawCmdBuffers[i].begin(cmdBufInfo);

			drawCmdBuffers[i].beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);

			vk::Viewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
			drawCmdBuffers[i].setViewport(0, viewport);

			vk::Rect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
			drawCmdBuffers[i].setScissor(0, scissor);

			drawCmdBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines.solid);

			for (auto& gear : gears)
			{
				gear->draw(drawCmdBuffers[i], pipelineLayout);
			}

			drawCmdBuffers[i].endRenderPass();

			drawCmdBuffers[i].end();

		}
	}

	void draw()
	{
		// Get next image in the swap chain (back/front buffer)
		prepareFrame();
		// Command buffer to be sumitted to the queue
		submitInfo.commandBufferCount = 1;
		submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];

		// Submit to queue
		queue.submit(submitInfo, VK_NULL_HANDLE);

		submitFrame();

	}

	void prepareVertices()
	{
		// Gear definitions
		std::vector<float> innerRadiuses = { 1.0f, 0.5f, 1.3f };
		std::vector<float> outerRadiuses = { 4.0f, 2.0f, 2.0f };
		std::vector<float> widths = { 1.0f, 2.0f, 0.5f };
		std::vector<int32_t> toothCount = { 20, 10, 10 };
		std::vector<float> toothDepth = { 0.7f, 0.7f, 0.7f };
		std::vector<glm::vec3> colors = {
			glm::vec3(1.0f, 0.0f, 0.0f),
			glm::vec3(0.0f, 1.0f, 0.2f),
			glm::vec3(0.0f, 0.0f, 1.0f)
		};
		std::vector<glm::vec3> positions = {
			glm::vec3(-3.0, 0.0, 0.0),
			glm::vec3(3.1, 0.0, 0.0),
			glm::vec3(-3.1, -6.2, 0.0)
		};
		std::vector<float> rotationSpeeds = { 1.0f, -2.0f, -2.0f };
		std::vector<float> rotationStarts = { 0.0f, -9.0f, -30.0f };

		gears.resize(positions.size());
		for (int32_t i = 0; i < gears.size(); ++i)
		{
			gears[i] = new VulkanGear(device, this);
			gears[i]->generate(
				innerRadiuses[i],
				outerRadiuses[i],
				widths[i],
				toothCount[i],
				toothDepth[i],
				colors[i],
				positions[i],
				rotationSpeeds[i],
				rotationStarts[i]);
		}

		// Binding and attribute descriptions are shared across all gears
		vertices.bindingDescriptions.resize(1);
		vertices.bindingDescriptions[0] =
			vkTools::initializers::vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID, sizeof(Vertex), vk::VertexInputRate::eVertex);

		// Attribute descriptions
		// Describes memory layout and shader positions
		vertices.attributeDescriptions.resize(3);
		// Location 0 : Position
		vertices.attributeDescriptions[0] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 0, vk::Format::eR32G32B32Sfloat, 0);
		// Location 1 : Normal
		vertices.attributeDescriptions[1] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 1, vk::Format::eR32G32B32Sfloat, sizeof(float) * 3);
		// Location 2 : Color
		vertices.attributeDescriptions[2] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 2, vk::Format::eR32G32B32Sfloat, sizeof(float) * 6);

		vertices.inputState = vk::PipelineVertexInputStateCreateInfo();
		vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
		vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
		vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
		vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
	}

	void setupDescriptorPool()
	{
		// One UBO for each gears
		std::vector<vk::DescriptorPoolSize> poolSizes =
		{
			vkTools::initializers::descriptorPoolSize(vk::DescriptorType::eUniformBuffer, 3),
		};

		vk::DescriptorPoolCreateInfo descriptorPoolInfo =
			vkTools::initializers::descriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), // Three descriptor sets (for each gear)
				3);

		descriptorPool = device.createDescriptorPool(descriptorPoolInfo);
	}

	void setupDescriptorSetLayout()
	{
		std::vector<vk::DescriptorSetLayoutBinding> setLayoutBindings =
		{
			// Binding 0 : Vertex shader uniform buffer
			vkTools::initializers::descriptorSetLayoutBinding(
				vk::DescriptorType::eUniformBuffer,
				vk::ShaderStageFlagBits::eVertex,
				0)
		};

		vk::DescriptorSetLayoutCreateInfo descriptorLayout =
			vkTools::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), setLayoutBindings.size());

		descriptorSetLayout = device.createDescriptorSetLayout(descriptorLayout);

		vk::PipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
			vkTools::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);

		pipelineLayout = device.createPipelineLayout(pPipelineLayoutCreateInfo);

	}

	void setupDescriptorSets()
	{
		for (auto& gear : gears)
		{
			gear->setupDescriptorSet(descriptorPool, descriptorSetLayout);
		}
	}

	void preparePipelines()
	{
		vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState =
			vkTools::initializers::pipelineInputAssemblyStateCreateInfo(vk::PrimitiveTopology::eTriangleList, vk::PipelineInputAssemblyStateCreateFlags(), VK_FALSE);

		vk::PipelineRasterizationStateCreateInfo rasterizationState =
			vkTools::initializers::pipelineRasterizationStateCreateInfo(vk::PolygonMode::eFill, vk::CullModeFlagBits::eNone, vk::FrontFace::eClockwise);

		vk::PipelineColorBlendAttachmentState blendAttachmentState =
			vkTools::initializers::pipelineColorBlendAttachmentState();

		vk::PipelineColorBlendStateCreateInfo colorBlendState =
			vkTools::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);

		vk::PipelineDepthStencilStateCreateInfo depthStencilState =
			vkTools::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, vk::CompareOp::eLessOrEqual);

		vk::PipelineViewportStateCreateInfo viewportState =
			vkTools::initializers::pipelineViewportStateCreateInfo(1, 1);

		vk::PipelineMultisampleStateCreateInfo multisampleState =
			vkTools::initializers::pipelineMultisampleStateCreateInfo(vk::SampleCountFlagBits::e1);

		std::vector<vk::DynamicState> dynamicStateEnables = {
			vk::DynamicState::eViewport,
			vk::DynamicState::eScissor
		};
		vk::PipelineDynamicStateCreateInfo dynamicState =
			vkTools::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), dynamicStateEnables.size());

		// Solid rendering pipeline
		// Load shaders
		std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages;

		shaderStages[0] = loadShader(getAssetPath() + "shaders/gears.vert.spv", vk::ShaderStageFlagBits::eVertex);
		shaderStages[1] = loadShader(getAssetPath() + "shaders/gears.frag.spv", vk::ShaderStageFlagBits::eFragment);

		vk::GraphicsPipelineCreateInfo pipelineCreateInfo =
			vkTools::initializers::pipelineCreateInfo(pipelineLayout, renderPass);

		pipelineCreateInfo.pVertexInputState = &vertices.inputState;
		pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
		pipelineCreateInfo.pRasterizationState = &rasterizationState;
		pipelineCreateInfo.pColorBlendState = &colorBlendState;
		pipelineCreateInfo.pMultisampleState = &multisampleState;
		pipelineCreateInfo.pViewportState = &viewportState;
		pipelineCreateInfo.pDepthStencilState = &depthStencilState;
		pipelineCreateInfo.pDynamicState = &dynamicState;
		pipelineCreateInfo.stageCount = shaderStages.size();
		pipelineCreateInfo.pStages = shaderStages.data();

		pipelines.solid = device.createGraphicsPipelines(pipelineCache, pipelineCreateInfo, nullptr)[0];
	}

	void updateUniformBuffers()
	{
		glm::mat4 perspective = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.001f, 256.0f);
		for (auto& gear : gears)
		{
			gear->updateUniformBuffer(perspective, rotation, zoom, timer * 360.0f);
		}
	}

	void prepare()
	{
		VulkanExampleBase::prepare();
		prepareVertices();
		setupDescriptorSetLayout();
		preparePipelines();
		setupDescriptorPool();
		setupDescriptorSets();
		updateUniformBuffers();
		buildCommandBuffers();
		prepared = true;
	}

	virtual void render()
	{
		if (!prepared)
			return;
		vkDeviceWaitIdle(device);
		draw();
		vkDeviceWaitIdle(device);
		if (!paused)
		{
			updateUniformBuffers();
		}
	}

	virtual void viewChanged()
	{
		updateUniformBuffers();
	}
};

VulkanExample *vulkanExample;

#if defined(_WIN32)
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (vulkanExample != NULL)
	{
		vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam);
	}
	return (DefWindowProc(hWnd, uMsg, wParam, lParam));
}
#elif defined(__linux__) && !defined(__ANDROID__)
static void handleEvent(const xcb_generic_event_t *event)
{
	if (vulkanExample != NULL)
	{
		vulkanExample->handleEvent(event);
	}
}
#endif

// Main entry point
#if defined(_WIN32)
// Windows entry point
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
#elif defined(__ANDROID__)
// Android entry point
void android_main(android_app* state)
#elif defined(__linux__)
// Linux entry point
int main(const int argc, const char *argv[])
#endif
{
#if defined(__ANDROID__)
	// Removing this may cause the compiler to omit the main entry point
	// which would make the application crash at start
	app_dummy();
#endif
	vulkanExample = new VulkanExample();
#if defined(_WIN32)
	vulkanExample->setupWindow(hInstance, WndProc);
#elif defined(__ANDROID__)
	// Attach vulkan example to global android application state
	state->userData = vulkanExample;
	state->onAppCmd = VulkanExample::handleAppCommand;
	state->onInputEvent = VulkanExample::handleAppInput;
	vulkanExample->androidApp = state;
#elif defined(__linux__)
	vulkanExample->setupWindow();
#endif
#if !defined(__ANDROID__)
	vulkanExample->initSwapchain();
	vulkanExample->prepare();
#endif
	vulkanExample->renderLoop();
	delete(vulkanExample);
#if !defined(__ANDROID__)
	return 0;
#endif
}<commit_msg>Removing startup boilerplate<commit_after>/*
* Vulkan Example - Animated gears using multiple uniform buffers
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#include "vulkangear.h"
#include "vulkanexamplebase.h"

class VulkanExample : public VulkanExampleBase
{
public:
	struct {
		vk::PipelineVertexInputStateCreateInfo inputState;
		std::vector<vk::VertexInputBindingDescription> bindingDescriptions;
		std::vector<vk::VertexInputAttributeDescription> attributeDescriptions;
	} vertices;

	struct {
		vk::Pipeline solid;
	} pipelines;

	std::vector<VulkanGear*> gears;

	vk::PipelineLayout pipelineLayout;
	vk::DescriptorSetLayout descriptorSetLayout;

	VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
	{
		zoom = -16.0f;
		rotation = glm::vec3(-23.75, 41.25, 21.0);
		timerSpeed *= 0.25f;
		title = "Vulkan Example - Gears";
	}

	~VulkanExample()
	{
		// Clean up used Vulkan resources
		// Note : Inherited destructor cleans up resources stored in base class
		device.destroyPipeline(pipelines.solid);

		device.destroyPipelineLayout(pipelineLayout);
		device.destroyDescriptorSetLayout(descriptorSetLayout);

		for (auto& gear : gears)
		{
			delete(gear);
		}
	}

	void buildCommandBuffers()
	{
		vk::CommandBufferBeginInfo cmdBufInfo;

		vk::ClearValue clearValues[2];
		clearValues[0].color = defaultClearColor;
		clearValues[1].depthStencil = { 1.0f, 0 };

		vk::RenderPassBeginInfo renderPassBeginInfo;
		renderPassBeginInfo.renderPass = renderPass;
		renderPassBeginInfo.renderArea.offset.x = 0;
		renderPassBeginInfo.renderArea.offset.y = 0;
		renderPassBeginInfo.renderArea.extent.width = width;
		renderPassBeginInfo.renderArea.extent.height = height;
		renderPassBeginInfo.clearValueCount = 2;
		renderPassBeginInfo.pClearValues = clearValues;

		for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
		{
			// Set target frame buffer
			renderPassBeginInfo.framebuffer = frameBuffers[i];

			drawCmdBuffers[i].begin(cmdBufInfo);

			drawCmdBuffers[i].beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);

			vk::Viewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
			drawCmdBuffers[i].setViewport(0, viewport);

			vk::Rect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
			drawCmdBuffers[i].setScissor(0, scissor);

			drawCmdBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines.solid);

			for (auto& gear : gears)
			{
				gear->draw(drawCmdBuffers[i], pipelineLayout);
			}

			drawCmdBuffers[i].endRenderPass();

			drawCmdBuffers[i].end();

		}
	}

	void draw()
	{
		// Get next image in the swap chain (back/front buffer)
		prepareFrame();
		// Command buffer to be sumitted to the queue
		submitInfo.commandBufferCount = 1;
		submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];

		// Submit to queue
		queue.submit(submitInfo, VK_NULL_HANDLE);

		submitFrame();

	}

	void prepareVertices()
	{
		// Gear definitions
		std::vector<float> innerRadiuses = { 1.0f, 0.5f, 1.3f };
		std::vector<float> outerRadiuses = { 4.0f, 2.0f, 2.0f };
		std::vector<float> widths = { 1.0f, 2.0f, 0.5f };
		std::vector<int32_t> toothCount = { 20, 10, 10 };
		std::vector<float> toothDepth = { 0.7f, 0.7f, 0.7f };
		std::vector<glm::vec3> colors = {
			glm::vec3(1.0f, 0.0f, 0.0f),
			glm::vec3(0.0f, 1.0f, 0.2f),
			glm::vec3(0.0f, 0.0f, 1.0f)
		};
		std::vector<glm::vec3> positions = {
			glm::vec3(-3.0, 0.0, 0.0),
			glm::vec3(3.1, 0.0, 0.0),
			glm::vec3(-3.1, -6.2, 0.0)
		};
		std::vector<float> rotationSpeeds = { 1.0f, -2.0f, -2.0f };
		std::vector<float> rotationStarts = { 0.0f, -9.0f, -30.0f };

		gears.resize(positions.size());
		for (int32_t i = 0; i < gears.size(); ++i)
		{
			gears[i] = new VulkanGear(device, this);
			gears[i]->generate(
				innerRadiuses[i],
				outerRadiuses[i],
				widths[i],
				toothCount[i],
				toothDepth[i],
				colors[i],
				positions[i],
				rotationSpeeds[i],
				rotationStarts[i]);
		}

		// Binding and attribute descriptions are shared across all gears
		vertices.bindingDescriptions.resize(1);
		vertices.bindingDescriptions[0] =
			vkTools::initializers::vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID, sizeof(Vertex), vk::VertexInputRate::eVertex);

		// Attribute descriptions
		// Describes memory layout and shader positions
		vertices.attributeDescriptions.resize(3);
		// Location 0 : Position
		vertices.attributeDescriptions[0] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 0, vk::Format::eR32G32B32Sfloat, 0);
		// Location 1 : Normal
		vertices.attributeDescriptions[1] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 1, vk::Format::eR32G32B32Sfloat, sizeof(float) * 3);
		// Location 2 : Color
		vertices.attributeDescriptions[2] =
			vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 2, vk::Format::eR32G32B32Sfloat, sizeof(float) * 6);

		vertices.inputState = vk::PipelineVertexInputStateCreateInfo();
		vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
		vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
		vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
		vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
	}

	void setupDescriptorPool()
	{
		// One UBO for each gears
		std::vector<vk::DescriptorPoolSize> poolSizes =
		{
			vkTools::initializers::descriptorPoolSize(vk::DescriptorType::eUniformBuffer, 3),
		};

		vk::DescriptorPoolCreateInfo descriptorPoolInfo =
			vkTools::initializers::descriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), // Three descriptor sets (for each gear)
				3);

		descriptorPool = device.createDescriptorPool(descriptorPoolInfo);
	}

	void setupDescriptorSetLayout()
	{
		std::vector<vk::DescriptorSetLayoutBinding> setLayoutBindings =
		{
			// Binding 0 : Vertex shader uniform buffer
			vkTools::initializers::descriptorSetLayoutBinding(
				vk::DescriptorType::eUniformBuffer,
				vk::ShaderStageFlagBits::eVertex,
				0)
		};

		vk::DescriptorSetLayoutCreateInfo descriptorLayout =
			vkTools::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), setLayoutBindings.size());

		descriptorSetLayout = device.createDescriptorSetLayout(descriptorLayout);

		vk::PipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
			vkTools::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);

		pipelineLayout = device.createPipelineLayout(pPipelineLayoutCreateInfo);

	}

	void setupDescriptorSets()
	{
		for (auto& gear : gears)
		{
			gear->setupDescriptorSet(descriptorPool, descriptorSetLayout);
		}
	}

	void preparePipelines()
	{
		vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState =
			vkTools::initializers::pipelineInputAssemblyStateCreateInfo(vk::PrimitiveTopology::eTriangleList, vk::PipelineInputAssemblyStateCreateFlags(), VK_FALSE);

		vk::PipelineRasterizationStateCreateInfo rasterizationState =
			vkTools::initializers::pipelineRasterizationStateCreateInfo(vk::PolygonMode::eFill, vk::CullModeFlagBits::eNone, vk::FrontFace::eClockwise);

		vk::PipelineColorBlendAttachmentState blendAttachmentState =
			vkTools::initializers::pipelineColorBlendAttachmentState();

		vk::PipelineColorBlendStateCreateInfo colorBlendState =
			vkTools::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);

		vk::PipelineDepthStencilStateCreateInfo depthStencilState =
			vkTools::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, vk::CompareOp::eLessOrEqual);

		vk::PipelineViewportStateCreateInfo viewportState =
			vkTools::initializers::pipelineViewportStateCreateInfo(1, 1);

		vk::PipelineMultisampleStateCreateInfo multisampleState =
			vkTools::initializers::pipelineMultisampleStateCreateInfo(vk::SampleCountFlagBits::e1);

		std::vector<vk::DynamicState> dynamicStateEnables = {
			vk::DynamicState::eViewport,
			vk::DynamicState::eScissor
		};
		vk::PipelineDynamicStateCreateInfo dynamicState =
			vkTools::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), dynamicStateEnables.size());

		// Solid rendering pipeline
		// Load shaders
		std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages;

		shaderStages[0] = loadShader(getAssetPath() + "shaders/gears.vert.spv", vk::ShaderStageFlagBits::eVertex);
		shaderStages[1] = loadShader(getAssetPath() + "shaders/gears.frag.spv", vk::ShaderStageFlagBits::eFragment);

		vk::GraphicsPipelineCreateInfo pipelineCreateInfo =
			vkTools::initializers::pipelineCreateInfo(pipelineLayout, renderPass);

		pipelineCreateInfo.pVertexInputState = &vertices.inputState;
		pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
		pipelineCreateInfo.pRasterizationState = &rasterizationState;
		pipelineCreateInfo.pColorBlendState = &colorBlendState;
		pipelineCreateInfo.pMultisampleState = &multisampleState;
		pipelineCreateInfo.pViewportState = &viewportState;
		pipelineCreateInfo.pDepthStencilState = &depthStencilState;
		pipelineCreateInfo.pDynamicState = &dynamicState;
		pipelineCreateInfo.stageCount = shaderStages.size();
		pipelineCreateInfo.pStages = shaderStages.data();

		pipelines.solid = device.createGraphicsPipelines(pipelineCache, pipelineCreateInfo, nullptr)[0];
	}

	void updateUniformBuffers()
	{
		glm::mat4 perspective = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.001f, 256.0f);
		for (auto& gear : gears)
		{
			gear->updateUniformBuffer(perspective, rotation, zoom, timer * 360.0f);
		}
	}

	void prepare()
	{
		VulkanExampleBase::prepare();
		prepareVertices();
		setupDescriptorSetLayout();
		preparePipelines();
		setupDescriptorPool();
		setupDescriptorSets();
		updateUniformBuffers();
		buildCommandBuffers();
		prepared = true;
	}

	virtual void render()
	{
		if (!prepared)
			return;
		vkDeviceWaitIdle(device);
		draw();
		vkDeviceWaitIdle(device);
		if (!paused)
		{
			updateUniformBuffers();
		}
	}

	virtual void viewChanged()
	{
		updateUniformBuffers();
	}
};

RUN_EXAMPLE(VulkanExample)
<|endoftext|>


<commit_before>#include "monitor_window.h"

#include <glgui/rootpanel.h>
#include <tinker/renderer/renderer.h>
#include <tinker/profiler.h>
#include <tinker/cvar.h>

#include "panel_container.h"
#include "panel_console.h"

using namespace glgui;

CMonitorWindow::CMonitorWindow(int argc, char** argv)
: CApplication(argc, argv)
{
}

CRenderer* CMonitorWindow::CreateRenderer()
{
	size_t x, y;
	Application()->GetViewportSize(x, y);

	return new CRenderer(x, y);
}

void RegistrationUpdate()
{
	MonitorWindow()->RegistrationUpdate();
}

void ConsoleOutput(const char* pszText)
{
	MonitorWindow()->GetConsolePanel()->PrintConsole(pszText);
}

void CMonitorWindow::Run()
{
	Viewback()->Initialize(&::RegistrationUpdate, &ConsoleOutput);

	CVar::SetCVar("r_bloom", 0);

	SetupGUI();

	while (IsOpen())
	{
		CProfiler::BeginFrame();

		{
			TPROF("Frame");

			PollEvents();

			{
				TPROF("CViewbackClient::Update()")
				vb.Update();
			}

			Render();
		}

		CProfiler::Render();
		SwapBuffers();
	}
}

void CMonitorWindow::SetupGUI()
{
	m_pPanelContainer = RootPanel()->AddControl(new CPanelContainer());

	m_pPanelContainer->Setup();
}

void CMonitorWindow::RegistrationUpdate()
{
	m_pPanelContainer->RegistrationUpdate();
}

void CMonitorWindow::WindowResize(int x, int y)
{
	if (m_pPanelContainer)
		m_pPanelContainer->Layout();

	BaseClass::WindowResize(x, y);
}

void CMonitorWindow::SetMaximizedPanel(const glgui::CControl<class CPanel_Base>& pPanel)
{
	if (m_pPanelContainer)
		m_pPanelContainer->SetMaximizedPanel(pPanel);
}

CControl<CPanel_Console> CMonitorWindow::GetConsolePanel()
{
	return m_pPanelContainer->GetConsolePanel();
}
<commit_msg>Channel debug output to the Viewback Monitor console.<commit_after>#include "monitor_window.h"

#include <glgui/rootpanel.h>
#include <tinker/renderer/renderer.h>
#include <tinker/profiler.h>
#include <tinker/cvar.h>
#include <tinker_platform.h>

#include "panel_container.h"
#include "panel_console.h"

using namespace glgui;

CMonitorWindow::CMonitorWindow(int argc, char** argv)
: CApplication(argc, argv)
{
}

CRenderer* CMonitorWindow::CreateRenderer()
{
	size_t x, y;
	Application()->GetViewportSize(x, y);

	return new CRenderer(x, y);
}

void RegistrationUpdate()
{
	MonitorWindow()->RegistrationUpdate();
}

void ConsoleOutput(const char* pszText)
{
	MonitorWindow()->GetConsolePanel()->PrintConsole(pszText);
}

void DebugOutput(const char* pszText)
{
	TMsg(sprintf(tstring("VB: %s"), pszText));
}

void CMonitorWindow::Run()
{
	EnableMulticast();

	if (!Viewback()->Initialize(&::RegistrationUpdate, &ConsoleOutput, &DebugOutput))
		TError("Could not initialize Viewback.\n");

	CVar::SetCVar("r_bloom", 0);

	SetupGUI();

	while (IsOpen())
	{
		CProfiler::BeginFrame();

		{
			TPROF("Frame");

			PollEvents();

			{
				TPROF("CViewbackClient::Update()")
				vb.Update();
			}

			Render();
		}

		CProfiler::Render();
		SwapBuffers();
	}
}

void CMonitorWindow::SetupGUI()
{
	m_pPanelContainer = RootPanel()->AddControl(new CPanelContainer());

	m_pPanelContainer->Setup();
}

void CMonitorWindow::RegistrationUpdate()
{
	m_pPanelContainer->RegistrationUpdate();
}

void CMonitorWindow::WindowResize(int x, int y)
{
	if (m_pPanelContainer)
		m_pPanelContainer->Layout();

	BaseClass::WindowResize(x, y);
}

void CMonitorWindow::SetMaximizedPanel(const glgui::CControl<class CPanel_Base>& pPanel)
{
	if (m_pPanelContainer)
		m_pPanelContainer->SetMaximizedPanel(pPanel);
}

CControl<CPanel_Console> CMonitorWindow::GetConsolePanel()
{
	return m_pPanelContainer->GetConsolePanel();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <seastar/core/scheduling.hh>
#include <seastar/core/timer.hh>
#include <seastar/core/gate.hh>
#include <chrono>

// Simple proportional controller to adjust shares for processes for which a backlog can be clearly
// defined.
//
// Goal is to consume the backlog as fast as we can, but not so fast that we steal all the CPU from
// incoming requests, and at the same time minimize user-visible fluctuations in the quota.
//
// What that translates to is we'll try to keep the backlog's firt derivative at 0 (IOW, we keep
// backlog constant). As the backlog grows we increase CPU usage, decreasing CPU usage as the
// backlog diminishes.
//
// The exact point at which the controller stops determines the desired CPU usage. As the backlog
// grows and approach a maximum desired, we need to be more aggressive. We will therefore define two
// thresholds, and increase the constant as we cross them.
//
// Doing that divides the range in three (before the first, between first and second, and after
// second threshold), and we'll be slow to grow in the first region, grow normally in the second
// region, and aggressively in the third region.
//
// The constants q1 and q2 are used to determine the proportional factor at each stage.
class backlog_controller {
public:
    future<> shutdown() {
        _update_timer.cancel();
        return std::move(_inflight_update);
    }
protected:
    struct control_point {
        float input;
        float output;
    };

    seastar::scheduling_group _scheduling_group;
    const ::io_priority_class& _io_priority;
    std::chrono::milliseconds _interval;
    timer<> _update_timer;

    std::vector<control_point> _control_points;

    std::function<float()> _current_backlog;
    // updating shares for an I/O class may contact another shard and returns a future.
    future<> _inflight_update;

    virtual void update_controller(float quota);

    void adjust();

    backlog_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval,
                       std::vector<control_point> control_points, std::function<float()> backlog)
        : _scheduling_group(sg)
        , _io_priority(iop)
        , _interval(interval)
        , _update_timer([this] { adjust(); })
        , _control_points({{0,0}})
        , _current_backlog(std::move(backlog))
        , _inflight_update(make_ready_future<>())
    {
        _control_points.insert(_control_points.end(), control_points.begin(), control_points.end());
         _update_timer.arm_periodic(_interval);
    }

    // Used when the controllers are disabled and a static share is used
    // When that option is deprecated we should remove this.
    backlog_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares)
        : _scheduling_group(sg)
        , _io_priority(iop)
        , _inflight_update(make_ready_future<>())
    {
        update_controller(static_shares);
    }

    virtual ~backlog_controller() {}
public:
    backlog_controller(backlog_controller&&) = default;
    float backlog_of_shares(float shares) const;
    seastar::scheduling_group sg() {
        return _scheduling_group;
    }
};

// memtable flush CPU controller.
//
// - First threshold is the soft limit line,
// - Maximum is the point in which we'd stop consuming request,
// - Second threshold is halfway between them.
//
// Below the soft limit, we are in no particular hurry to flush, since it means we're set to
// complete flushing before we a new memtable is ready. The quota is dirty * q1, and q1 is set to a
// low number.
//
// The first half of the virtual dirty region is where we expect to be usually, so we have a low
// slope corresponding to a sluggish response between q1 * soft_limit and q2.
//
// In the second half, we're getting close to the hard dirty limit so we increase the slope and
// become more responsive, up to a maximum quota of qmax.
class flush_controller : public backlog_controller {
    static constexpr float hard_dirty_limit = 1.0f;
public:
    flush_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares) : backlog_controller(sg, iop, static_shares) {}
    flush_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval, float soft_limit, std::function<float()> current_dirty)
        : backlog_controller(sg, iop, std::move(interval),
          std::vector<backlog_controller::control_point>({{soft_limit, 10}, {soft_limit + (hard_dirty_limit - soft_limit) / 2, 200} , {hard_dirty_limit, 1000}}),
          std::move(current_dirty)
        )
    {}
};

class compaction_controller : public backlog_controller {
public:
    static constexpr unsigned normalization_factor = 30;
    static constexpr float disable_backlog = std::numeric_limits<double>::infinity();
    static constexpr float backlog_disabled(float backlog) { return std::isinf(backlog); }
    compaction_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares) : backlog_controller(sg, iop, static_shares) {}
    compaction_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval, std::function<float()> current_backlog)
        : backlog_controller(sg, iop, std::move(interval),
          std::vector<backlog_controller::control_point>({{0.5, 10}, {1.5, 100} , {normalization_factor, 1000}}),
          std::move(current_backlog)
        )
    {}
};
<commit_msg>compaction_controller: increase minimum shares to 50 (~5%) for small-data workloads<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <seastar/core/scheduling.hh>
#include <seastar/core/timer.hh>
#include <seastar/core/gate.hh>
#include <chrono>

// Simple proportional controller to adjust shares for processes for which a backlog can be clearly
// defined.
//
// Goal is to consume the backlog as fast as we can, but not so fast that we steal all the CPU from
// incoming requests, and at the same time minimize user-visible fluctuations in the quota.
//
// What that translates to is we'll try to keep the backlog's firt derivative at 0 (IOW, we keep
// backlog constant). As the backlog grows we increase CPU usage, decreasing CPU usage as the
// backlog diminishes.
//
// The exact point at which the controller stops determines the desired CPU usage. As the backlog
// grows and approach a maximum desired, we need to be more aggressive. We will therefore define two
// thresholds, and increase the constant as we cross them.
//
// Doing that divides the range in three (before the first, between first and second, and after
// second threshold), and we'll be slow to grow in the first region, grow normally in the second
// region, and aggressively in the third region.
//
// The constants q1 and q2 are used to determine the proportional factor at each stage.
class backlog_controller {
public:
    future<> shutdown() {
        _update_timer.cancel();
        return std::move(_inflight_update);
    }
protected:
    struct control_point {
        float input;
        float output;
    };

    seastar::scheduling_group _scheduling_group;
    const ::io_priority_class& _io_priority;
    std::chrono::milliseconds _interval;
    timer<> _update_timer;

    std::vector<control_point> _control_points;

    std::function<float()> _current_backlog;
    // updating shares for an I/O class may contact another shard and returns a future.
    future<> _inflight_update;

    virtual void update_controller(float quota);

    void adjust();

    backlog_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval,
                       std::vector<control_point> control_points, std::function<float()> backlog)
        : _scheduling_group(sg)
        , _io_priority(iop)
        , _interval(interval)
        , _update_timer([this] { adjust(); })
        , _control_points()
        , _current_backlog(std::move(backlog))
        , _inflight_update(make_ready_future<>())
    {
        _control_points.insert(_control_points.end(), control_points.begin(), control_points.end());
         _update_timer.arm_periodic(_interval);
    }

    // Used when the controllers are disabled and a static share is used
    // When that option is deprecated we should remove this.
    backlog_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares)
        : _scheduling_group(sg)
        , _io_priority(iop)
        , _inflight_update(make_ready_future<>())
    {
        update_controller(static_shares);
    }

    virtual ~backlog_controller() {}
public:
    backlog_controller(backlog_controller&&) = default;
    float backlog_of_shares(float shares) const;
    seastar::scheduling_group sg() {
        return _scheduling_group;
    }
};

// memtable flush CPU controller.
//
// - First threshold is the soft limit line,
// - Maximum is the point in which we'd stop consuming request,
// - Second threshold is halfway between them.
//
// Below the soft limit, we are in no particular hurry to flush, since it means we're set to
// complete flushing before we a new memtable is ready. The quota is dirty * q1, and q1 is set to a
// low number.
//
// The first half of the virtual dirty region is where we expect to be usually, so we have a low
// slope corresponding to a sluggish response between q1 * soft_limit and q2.
//
// In the second half, we're getting close to the hard dirty limit so we increase the slope and
// become more responsive, up to a maximum quota of qmax.
class flush_controller : public backlog_controller {
    static constexpr float hard_dirty_limit = 1.0f;
public:
    flush_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares) : backlog_controller(sg, iop, static_shares) {}
    flush_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval, float soft_limit, std::function<float()> current_dirty)
        : backlog_controller(sg, iop, std::move(interval),
          std::vector<backlog_controller::control_point>({{0.0, 0.0}, {soft_limit, 10}, {soft_limit + (hard_dirty_limit - soft_limit) / 2, 200} , {hard_dirty_limit, 1000}}),
          std::move(current_dirty)
        )
    {}
};

class compaction_controller : public backlog_controller {
public:
    static constexpr unsigned normalization_factor = 30;
    static constexpr float disable_backlog = std::numeric_limits<double>::infinity();
    static constexpr float backlog_disabled(float backlog) { return std::isinf(backlog); }
    compaction_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, float static_shares) : backlog_controller(sg, iop, static_shares) {}
    compaction_controller(seastar::scheduling_group sg, const ::io_priority_class& iop, std::chrono::milliseconds interval, std::function<float()> current_backlog)
        : backlog_controller(sg, iop, std::move(interval),
          std::vector<backlog_controller::control_point>({{0.0, 50}, {1.5, 100} , {normalization_factor, 1000}}),
          std::move(current_backlog)
        )
    {}
};
<|endoftext|>