<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "ClientRegister.h"
#include "SyncThread.h"
#include "ILoginListener.h"
#include "common/RhoConf.h"
#include "common/RhodesApp.h"
#include "System.h"

rho::String rho_sysimpl_get_phone_id();

namespace rho{
namespace sync{

using namespace rho::common;
using namespace rho::db;

static const int THREAD_WAIT_TIMEOUT = 10;

IMPLEMENT_LOGCLASS(CClientRegister,"ClientRegister");

CClientRegister* CClientRegister::m_pInstance = 0;
bool CClientRegister::s_sslVerifyPeer = true;
VectorPtr<ILoginListener*> CClientRegister::s_loginListeners;

/*static*/ CClientRegister* CClientRegister::Get()
{
    if (!m_pInstance)
    {
        m_pInstance = new CClientRegister();
    }
    return m_pInstance;
}

/*static*/ CClientRegister* CClientRegister::Create()
{
    LOG(TRACE) + "Loading rhoconnect session...";
    String session = CSyncThread::getSyncEngine().loadSession();
    if (session.length() > 0)
    {
        LOG(TRACE) + "Loaded";
        Get()->setRhoconnectCredentials("", "", session);
    }
    LOG(TRACE) + "Starting ClientRegister";
    Get()->startUp();
    return m_pInstance;
}

/*static*/ CClientRegister* CClientRegister::Create(const String& devicePin)
{
    Get()->setDevicehPin(devicePin);
    return m_pInstance;
}

/*static*/ void CClientRegister::Stop()
{
    if(m_pInstance)
    {
        m_pInstance->doStop();
    }
}

/*static*/ void CClientRegister::Destroy()
{
    if ( m_pInstance )
        delete m_pInstance;

    m_pInstance = 0;
}

/*static*/ void CClientRegister::SetSslVerifyPeer(boolean b)
{
    s_sslVerifyPeer = b;
    if (m_pInstance)
        m_pInstance->m_NetRequest.setSslVerifyPeer(b);
}

bool CClientRegister::GetSslVerifyPeer()
{
    return s_sslVerifyPeer;
}

/*static*/void CClientRegister::AddLoginListener(ILoginListener* listener)
{
    s_loginListeners.addElement(listener);
}

CClientRegister::CClientRegister() : m_nPollInterval(POLL_INTERVAL_SECONDS)
{
    m_NetRequest.setSslVerifyPeer(s_sslVerifyPeer);

}

CClientRegister::~CClientRegister()
{
    doStop();
    m_pInstance = null;
}
void CClientRegister::setRhoconnectCredentials(const String& user, const String& pass, const String& session)
{
    LOG(INFO) + "New Sync credentials - user: " + user + ", sess: " + session;

    for(VectorPtr<ILoginListener*>::iterator I = s_loginListeners.begin(); I != s_loginListeners.end(); ++I)
    {
        (*I)->onLogin(user, pass, session);
    }
    startUp();
}

void CClientRegister::dropRhoconnectCredentials(const String& session)
{
    for(VectorPtr<ILoginListener*>::iterator I = s_loginListeners.begin(); I != s_loginListeners.end(); ++I)
    {
        (*I)->onLogout(session);
    }
}

void CClientRegister::setDevicehPin(const String& pin)
{
    m_strDevicePin = pin;

    if (pin.length() > 0)
    {
        startUp();
    } else
    {
        doStop();
    }
}

void CClientRegister::startUp()
{
    if ( RHOCONF().getString("syncserver").length() > 0 )
    {
        LOG(INFO) + "Starting ClientRegister...";

        start(epLow);
        stopWait();
    }
}

void CClientRegister::run()
{
    unsigned i = 0;
    LOG(INFO)+"ClientRegister is started";
	while(!isStopping())
	{
        i++;
        LOG(INFO)+"Try to register: " + i;
        if ( CSyncThread::getInstance() != null )
		{
			if ( doRegister(CSyncThread::getSyncEngine()) )
			{
			    LOG(INFO)+"Registered: " + i;
				break;
			}
		} else
		    LOG(INFO)+"SyncThread is not ready";

		LOG(INFO)+"Waiting for "+ m_nPollInterval+ " sec to try again to register client";
		wait(m_nPollInterval*1000);
	}
    LOG(INFO)+"ClientRegister thread shutdown";
}

String CClientRegister::getRegisterBody(const String& strClientID)
{
	IRhoPushClient* pushClient = RHODESAPP().getDefaultPushClient();
	int port = RHOCONF().getInt("push_port");

	String body = CSyncThread::getSyncEngine().getProtocol().getClientRegisterBody( strClientID, m_strDevicePin,
		port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho::System::getPhoneId(),
        /*device_push_type*/ (0 != pushClient) ? pushClient->getType() : "" /*it means native push type*/);

	LOG(INFO)+"getRegisterBody() BODY is: " + body;
	return body;

	/*
    if(m_isAns)
		body = CSyncThread::getSyncEngine().getProtocol().getClientAnsRegisterBody( strClientID, m_strDevicePin,
			port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho_sysimpl_get_phone_id() );
	else
		body = CSyncThread::getSyncEngine().getProtocol().getClientRegisterBody( strClientID, m_strDevicePin,
			port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho_sysimpl_get_phone_id() );
	*/

}

boolean CClientRegister::doRegister(CSyncEngine& oSync)
{
    String session = oSync.loadSession();
    if ( session.length() == 0 )
    {
        m_nPollInterval = POLL_INTERVAL_INFINITE;
        LOG(INFO)+"Session is empty, do register later";
        return false;
    }
    if ( m_strDevicePin.length() == 0 )
    {
        m_nPollInterval = POLL_INTERVAL_INFINITE;
        LOG(INFO)+"Device PUSH pin is empty, do register later";
        return false;
    }
    m_nPollInterval = POLL_INTERVAL_SECONDS;

	String client_id = oSync.loadClientID();
	if ( client_id.length() == 0 )
	{
        LOG(WARNING)+"Sync client_id is empty, do register later";
		return false;
	}

    IDBResult res = CDBAdapter::getUserDB().executeSQL("SELECT token,token_sent from client_info");
    if ( !res.isEnd() ) {
		String token = res.getStringByIdx(0);
		int token_sent = res.getIntByIdx(1) && !RHOCONF().getBool("register_push_at_startup");
		if ( m_strDevicePin.compare(token) == 0 && token_sent > 0 )
		{
			//token in db same as new one and it was already send to the server
			//so we do nothing
			return true;
		}
    }
	String strBody = getRegisterBody(client_id);
    NetResponse resp = getNet().pushData( oSync.getProtocol().getClientRegisterUrl(client_id), strBody, &oSync );
	if( resp.isOK() )
    {
//				try {
			CDBAdapter::getUserDB().executeSQL("UPDATE client_info SET token_sent=?, token=?", 1, m_strDevicePin );
//				} catch(Exception ex) {
//					LOG.ERROR("Error saving token_sent to the DB...");
//				}
		LOG(INFO)+"Registered client sucessfully...";
		return true;
	}

	LOG(WARNING)+"Network error: "+ resp.getRespCode();
	return false;
}

void CClientRegister::doStop()
{
    LOG(INFO) + "Stopping ClientRegister...";

    m_NetRequest.cancel();
    stop(WAIT_BEFOREKILL_SECONDS);
}

}
}
<commit_msg>fixed crash: load session only after syncthread is started.<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "ClientRegister.h"
#include "SyncThread.h"
#include "ILoginListener.h"
#include "common/RhoConf.h"
#include "common/RhodesApp.h"
#include "System.h"

rho::String rho_sysimpl_get_phone_id();

namespace rho{
namespace sync{

using namespace rho::common;
using namespace rho::db;

static const int THREAD_WAIT_TIMEOUT = 10;

IMPLEMENT_LOGCLASS(CClientRegister,"ClientRegister");

CClientRegister* CClientRegister::m_pInstance = 0;
bool CClientRegister::s_sslVerifyPeer = true;
VectorPtr<ILoginListener*> CClientRegister::s_loginListeners;

/*static*/ CClientRegister* CClientRegister::Get()
{
    if (!m_pInstance)
    {
        m_pInstance = new CClientRegister();
    }
    return m_pInstance;
}

/*static*/ CClientRegister* CClientRegister::Create()
{
    LOG(TRACE) + "Starting ClientRegister";
    Get()->startUp();
    return m_pInstance;
}

/*static*/ CClientRegister* CClientRegister::Create(const String& devicePin)
{
    Get()->setDevicehPin(devicePin);
    return m_pInstance;
}

/*static*/ void CClientRegister::Stop()
{
    if(m_pInstance)
    {
        m_pInstance->doStop();
    }
}

/*static*/ void CClientRegister::Destroy()
{
    if ( m_pInstance )
        delete m_pInstance;

    m_pInstance = 0;
}

/*static*/ void CClientRegister::SetSslVerifyPeer(boolean b)
{
    s_sslVerifyPeer = b;
    if (m_pInstance)
        m_pInstance->m_NetRequest.setSslVerifyPeer(b);
}

bool CClientRegister::GetSslVerifyPeer()
{
    return s_sslVerifyPeer;
}

/*static*/void CClientRegister::AddLoginListener(ILoginListener* listener)
{
    s_loginListeners.addElement(listener);
}

CClientRegister::CClientRegister() : m_nPollInterval(POLL_INTERVAL_SECONDS)
{
    m_NetRequest.setSslVerifyPeer(s_sslVerifyPeer);
}

CClientRegister::~CClientRegister()
{
    doStop();
    m_pInstance = null;
}
void CClientRegister::setRhoconnectCredentials(const String& user, const String& pass, const String& session)
{
    LOG(INFO) + "New Sync credentials - user: " + user + ", sess: " + session;

    for(VectorPtr<ILoginListener*>::iterator I = s_loginListeners.begin(); I != s_loginListeners.end(); ++I)
    {
        (*I)->onLogin(user, pass, session);
    }
    startUp();
}

void CClientRegister::dropRhoconnectCredentials(const String& session)
{
    for(VectorPtr<ILoginListener*>::iterator I = s_loginListeners.begin(); I != s_loginListeners.end(); ++I)
    {
        (*I)->onLogout(session);
    }
}

void CClientRegister::setDevicehPin(const String& pin)
{
    m_strDevicePin = pin;

    if (pin.length() > 0)
    {
        startUp();
    } else
    {
        doStop();
    }
}

void CClientRegister::startUp()
{
    if ( RHOCONF().getString("syncserver").length() > 0 )
    {
        LOG(INFO) + "Starting ClientRegister...";

        start(epLow);
        stopWait();
    }
}

void CClientRegister::run()
{
    unsigned i = 0;
    LOG(INFO)+"ClientRegister is started";
	while(!isStopping())
	{
        i++;
        LOG(INFO)+"Try to register: " + i;
        if ( CSyncThread::getInstance() != null )
		{
			if ( doRegister(CSyncThread::getSyncEngine()) )
			{
			    LOG(INFO)+"Registered: " + i;
				break;
			}
		} else
		    LOG(INFO)+"SyncThread is not ready";

		LOG(INFO)+"Waiting for "+ m_nPollInterval+ " sec to try again to register client";
		wait(m_nPollInterval*1000);
	}
    LOG(INFO)+"ClientRegister thread shutdown";
}

String CClientRegister::getRegisterBody(const String& strClientID)
{
	IRhoPushClient* pushClient = RHODESAPP().getDefaultPushClient();
	int port = RHOCONF().getInt("push_port");

	String body = CSyncThread::getSyncEngine().getProtocol().getClientRegisterBody( strClientID, m_strDevicePin,
		port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho::System::getPhoneId(),
        /*device_push_type*/ (0 != pushClient) ? pushClient->getType() : "" /*it means native push type*/);

	LOG(INFO)+"getRegisterBody() BODY is: " + body;
	return body;

	/*
    if(m_isAns)
		body = CSyncThread::getSyncEngine().getProtocol().getClientAnsRegisterBody( strClientID, m_strDevicePin,
			port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho_sysimpl_get_phone_id() );
	else
		body = CSyncThread::getSyncEngine().getProtocol().getClientRegisterBody( strClientID, m_strDevicePin,
			port > 0 ? port : DEFAULT_PUSH_PORT, rho_rhodesapp_getplatform(), rho_sysimpl_get_phone_id() );
	*/

}

boolean CClientRegister::doRegister(CSyncEngine& oSync)
{
    String session = oSync.loadSession();
    if ( session.length() == 0 )
    {
        m_nPollInterval = POLL_INTERVAL_INFINITE;
        LOG(INFO)+"Session is empty, do register later";
        return false;
    }

    Get()->setRhoconnectCredentials("", "", session);

    if ( m_strDevicePin.length() == 0 )
    {
        m_nPollInterval = POLL_INTERVAL_INFINITE;
        LOG(INFO)+"Device PUSH pin is empty, do register later";
        return false;
    }
    m_nPollInterval = POLL_INTERVAL_SECONDS;

	String client_id = oSync.loadClientID();
	if ( client_id.length() == 0 )
	{
        LOG(WARNING)+"Sync client_id is empty, do register later";
		return false;
	}

    IDBResult res = CDBAdapter::getUserDB().executeSQL("SELECT token,token_sent from client_info");
    if ( !res.isEnd() ) {
		String token = res.getStringByIdx(0);
		int token_sent = res.getIntByIdx(1) && !RHOCONF().getBool("register_push_at_startup");
		if ( m_strDevicePin.compare(token) == 0 && token_sent > 0 )
		{
			//token in db same as new one and it was already send to the server
			//so we do nothing
			return true;
		}
    }
	String strBody = getRegisterBody(client_id);
    NetResponse resp = getNet().pushData( oSync.getProtocol().getClientRegisterUrl(client_id), strBody, &oSync );
	if( resp.isOK() )
    {
//				try {
			CDBAdapter::getUserDB().executeSQL("UPDATE client_info SET token_sent=?, token=?", 1, m_strDevicePin );
//				} catch(Exception ex) {
//					LOG.ERROR("Error saving token_sent to the DB...");
//				}
		LOG(INFO)+"Registered client sucessfully...";
		return true;
	}

	LOG(WARNING)+"Network error: "+ resp.getRespCode();
	return false;
}

void CClientRegister::doStop()
{
    LOG(INFO) + "Stopping ClientRegister...";

    m_NetRequest.cancel();
    stop(WAIT_BEFOREKILL_SECONDS);
}

}
}
<|endoftext|>


<commit_before>#include "../tesselator.hpp"
#include "../geometry_serialization.hpp"
#include "../mercator.hpp"
#include "../point_to_int64.hpp"
#include "../coding_params.hpp"

#include "../../coding/reader.hpp"
#include "../../coding/writer.hpp"

#include "../../testing/testing.hpp"

namespace
{
  typedef m2::PointD P;

  bool is_equal(P const & p1, P const & p2)
  {
    return p1.EqualDxDy(p2, MercatorBounds::GetCellID2PointAbsEpsilon());
  }

  bool FindTriangle(serial::OutPointsT const & test, P arr[])
  {
    size_t const count = test.size();
    for (size_t i = 0; i < count; i+=3)
    {
      for (int base = 0; base < 3; ++base)
        if (is_equal(test[i], arr[base]) &&
            is_equal(test[i+1], arr[(base+1)%3]) &&
            is_equal(test[i+2], arr[(base+2)%3]))
        {
          return true;
        }
    }
    return false;
  }

  void CompareTriangles(serial::OutPointsT const & test,
                        P arrP[], uintptr_t arrT[][3], size_t count)
  {
    TEST_EQUAL(test.size(), 3*count, (test));

    for (size_t i = 0; i < count; ++i)
    {
      P trg[] = { arrP[arrT[i][0]], arrP[arrT[i][1]], arrP[arrT[i][2]] };
      TEST ( FindTriangle(test, trg), ("Triangles : ", test, " Etalon : ", trg[0], trg[1], trg[2]) );
    }
  }

  void TestTrianglesCoding(P arrP[], size_t countP, uintptr_t arrT[][3], size_t countT)
  {
    tesselator::TrianglesInfo info;
    info.AssignPoints(arrP, arrP + countP);

    info.Reserve(countT);

    for (size_t i = 0; i < countT; ++i)
      info.Add(arrT[i]);

    serial::CodingParams codingParams;
    serial::TrianglesChainSaver saver(codingParams);
    tesselator::PointsInfo points;
    m2::PointU (* D2U)(m2::PointD const &, uint32_t) = &PointD2PointU;
    info.GetPointsInfo(saver.GetBasePoint(), saver.GetMaxPoint(),
                       bind(D2U, _1, codingParams.GetCoordBits()), points);

    info.ProcessPortions(points, saver);

    vector<char> buffer;
    MemWriter<vector<char> > writer(buffer);
    saver.Save(writer);

    TEST ( !buffer.empty(), () );

    MemReader reader(&buffer[0], buffer.size());
    ReaderSource<MemReader> src(reader);

    serial::OutPointsT triangles;
    serial::LoadOuterTriangles(src, serial::CodingParams(), triangles);

    CompareTriangles(triangles, arrP, arrT, countT);
  }
}

UNIT_TEST(TrianglesCoding_Smoke)
{
  {
    P arrP[] =  { P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(0, -1), P(-1, 0) };
    uintptr_t arrT[][3] = { {0, 1, 2}, {1, 3, 2}, {4, 0, 2}, {1, 0, 5}, {4, 5, 0} };

    TestTrianglesCoding(arrP, ARRAY_SIZE(arrP), arrT, ARRAY_SIZE(arrT));
  }
}
<commit_msg>Compilation fix: include path.<commit_after>#include "../tesselator.hpp"

#include "../../indexer/geometry_serialization.hpp"
#include "../../indexer/mercator.hpp"
#include "../../indexer/point_to_int64.hpp"
#include "../../indexer/coding_params.hpp"

#include "../../coding/reader.hpp"
#include "../../coding/writer.hpp"

#include "../../testing/testing.hpp"

namespace
{
  typedef m2::PointD P;

  bool is_equal(P const & p1, P const & p2)
  {
    return p1.EqualDxDy(p2, MercatorBounds::GetCellID2PointAbsEpsilon());
  }

  bool FindTriangle(serial::OutPointsT const & test, P arr[])
  {
    size_t const count = test.size();
    for (size_t i = 0; i < count; i+=3)
    {
      for (int base = 0; base < 3; ++base)
        if (is_equal(test[i], arr[base]) &&
            is_equal(test[i+1], arr[(base+1)%3]) &&
            is_equal(test[i+2], arr[(base+2)%3]))
        {
          return true;
        }
    }
    return false;
  }

  void CompareTriangles(serial::OutPointsT const & test,
                        P arrP[], uintptr_t arrT[][3], size_t count)
  {
    TEST_EQUAL(test.size(), 3*count, (test));

    for (size_t i = 0; i < count; ++i)
    {
      P trg[] = { arrP[arrT[i][0]], arrP[arrT[i][1]], arrP[arrT[i][2]] };
      TEST ( FindTriangle(test, trg), ("Triangles : ", test, " Etalon : ", trg[0], trg[1], trg[2]) );
    }
  }

  void TestTrianglesCoding(P arrP[], size_t countP, uintptr_t arrT[][3], size_t countT)
  {
    tesselator::TrianglesInfo info;
    info.AssignPoints(arrP, arrP + countP);

    info.Reserve(countT);

    for (size_t i = 0; i < countT; ++i)
      info.Add(arrT[i]);

    serial::CodingParams codingParams;
    serial::TrianglesChainSaver saver(codingParams);
    tesselator::PointsInfo points;
    m2::PointU (* D2U)(m2::PointD const &, uint32_t) = &PointD2PointU;
    info.GetPointsInfo(saver.GetBasePoint(), saver.GetMaxPoint(),
                       bind(D2U, _1, codingParams.GetCoordBits()), points);

    info.ProcessPortions(points, saver);

    vector<char> buffer;
    MemWriter<vector<char> > writer(buffer);
    saver.Save(writer);

    TEST ( !buffer.empty(), () );

    MemReader reader(&buffer[0], buffer.size());
    ReaderSource<MemReader> src(reader);

    serial::OutPointsT triangles;
    serial::LoadOuterTriangles(src, serial::CodingParams(), triangles);

    CompareTriangles(triangles, arrP, arrT, countT);
  }
}

UNIT_TEST(TrianglesCoding_Smoke)
{
  {
    P arrP[] =  { P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(0, -1), P(-1, 0) };
    uintptr_t arrT[][3] = { {0, 1, 2}, {1, 3, 2}, {4, 0, 2}, {1, 0, 5}, {4, 5, 0} };

    TestTrianglesCoding(arrP, ARRAY_SIZE(arrP), arrT, ARRAY_SIZE(arrT));
  }
}
<|endoftext|>


<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/unit.hpp>
#include <agency/detail/type_traits.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{

template<class Factory>
using result_of_factory_t = result_of_t<Factory()>;

// construct is a type of Factory
// which creates a T by calling T's constructor with the given Args...
template<class T, class... Args>
class construct
{
  public:
    __AGENCY_ANNOTATION
    construct() : args_() {}

    __AGENCY_ANNOTATION
    construct(const tuple<Args...>& args)
      : args_(args)
    {}

    // XXX eliminate me!
    __AGENCY_ANNOTATION
    T make() const &
    {
      return __tu::make_from_tuple<T>(args_);
    }

    // XXX eliminate me!
    __AGENCY_ANNOTATION
    T make() &&
    {
      return __tu::make_from_tuple<T>(std::move(args_));
    }

    __AGENCY_ANNOTATION
    T operator()() const &
    {
      return make();
    }

    __AGENCY_ANNOTATION
    T operator()() &&
    {
      return std::move(*this).make();
    }

  private:
    tuple<Args...> args_;
};

template<class T, class... Args>
__AGENCY_ANNOTATION
construct<T,typename std::decay<Args>::type...> make_construct(Args&&... args)
{
  return construct<T,typename std::decay<Args>::type...>(agency::detail::make_tuple(std::forward<Args>(args)...));
}

template<class T>
__AGENCY_ANNOTATION
construct<T,T> make_copy_construct(const T& arg)
{
  return make_construct<T>(arg);
}

struct unit_factory : construct<unit> {};

// a moving_factory is a factory which moves an object when it is called
template<class T>
class moving_factory
{
  public:
    // XXX this code causes nvcc 8.0 to produce an error message
    //
    //__agency_exec_check_disable__
    //template<class U,
    //         class = typename std::enable_if<
    //           std::is_constructible<T,U&&>::value
    //         >::type>
    //__AGENCY_ANNOTATION
    //moving_factory(U&& value)
    //  : value_(std::forward<U>(value))
    //{}

    // XXX in order to WAR the nvcc 8.0 error above,
    //     instead of perfectly forwarding the value in,
    //     move construct it into value_ instead.
    __agency_exec_check_disable__
    __AGENCY_ANNOTATION
    moving_factory(T&& value)
      : value_(std::move(value))
    {}

    __AGENCY_ANNOTATION
    T operator()() const
    {
      return std::move(value_);
    }

  private:
    mutable T value_;
};

template<class T>
moving_factory<decay_t<T>> make_moving_factory(T&& value)
{
  return moving_factory<decay_t<T>>(std::forward<T>(value));
}

// a zip_factory is a type of Factory which takes a list of Factories
// and creates a tuple whose elements are the results of the given Factories
template<class... Factories>
struct zip_factory
{
  tuple<Factories...> factory_tuple_;

  __AGENCY_ANNOTATION
  zip_factory(const tuple<Factories...>& factories) : factory_tuple_(factories) {}

  template<size_t... Indices>
  __AGENCY_ANNOTATION
  agency::detail::tuple<
    result_of_factory_t<Factories>...
  >
    impl(agency::detail::index_sequence<Indices...>)
  {
    return agency::detail::make_tuple(detail::get<Indices>(factory_tuple_)()...);
  }

  __AGENCY_ANNOTATION
  agency::detail::tuple<
    result_of_factory_t<Factories>...
  >
    operator()()
  {
    return impl(index_sequence_for<Factories...>());
  }
};

template<class... Factories>
__AGENCY_ANNOTATION
zip_factory<Factories...> make_zip_factory(const tuple<Factories...>& factory_tuple)
{
  return zip_factory<Factories...>(factory_tuple);
}

} // end detail
} // end agency

<commit_msg>Give moving_factory a copy constructor<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/unit.hpp>
#include <agency/detail/type_traits.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{

template<class Factory>
using result_of_factory_t = result_of_t<Factory()>;

// construct is a type of Factory
// which creates a T by calling T's constructor with the given Args...
template<class T, class... Args>
class construct
{
  public:
    __AGENCY_ANNOTATION
    construct() : args_() {}

    __AGENCY_ANNOTATION
    construct(const tuple<Args...>& args)
      : args_(args)
    {}

    // XXX eliminate me!
    __AGENCY_ANNOTATION
    T make() const &
    {
      return __tu::make_from_tuple<T>(args_);
    }

    // XXX eliminate me!
    __AGENCY_ANNOTATION
    T make() &&
    {
      return __tu::make_from_tuple<T>(std::move(args_));
    }

    __AGENCY_ANNOTATION
    T operator()() const &
    {
      return make();
    }

    __AGENCY_ANNOTATION
    T operator()() &&
    {
      return std::move(*this).make();
    }

  private:
    tuple<Args...> args_;
};

template<class T, class... Args>
__AGENCY_ANNOTATION
construct<T,typename std::decay<Args>::type...> make_construct(Args&&... args)
{
  return construct<T,typename std::decay<Args>::type...>(agency::detail::make_tuple(std::forward<Args>(args)...));
}

template<class T>
__AGENCY_ANNOTATION
construct<T,T> make_copy_construct(const T& arg)
{
  return make_construct<T>(arg);
}

struct unit_factory : construct<unit> {};

// a moving_factory is a factory which moves an object when it is called
template<class T>
class moving_factory
{
  public:
    __AGENCY_ANNOTATION
    moving_factory(moving_factory&& other) = default;

    // this constructor moves other's value into value_
    // so, it acts like a move constructor
    __AGENCY_ANNOTATION
    moving_factory(const moving_factory& other)
      : value_(std::move(other.value_))
    {}

    // XXX this code causes nvcc 8.0 to produce an error message
    //
    //__agency_exec_check_disable__
    //template<class U,
    //         class = typename std::enable_if<
    //           std::is_constructible<T,U&&>::value
    //         >::type>
    //__AGENCY_ANNOTATION
    //moving_factory(U&& value)
    //  : value_(std::forward<U>(value))
    //{}

    // XXX in order to WAR the nvcc 8.0 error above,
    //     instead of perfectly forwarding the value in,
    //     move construct it into value_ instead.
    __agency_exec_check_disable__
    __AGENCY_ANNOTATION
    moving_factory(T&& value)
      : value_(std::move(value))
    {}

    __AGENCY_ANNOTATION
    T operator()() const
    {
      return std::move(value_);
    }

  private:
    mutable T value_;
};

template<class T>
moving_factory<decay_t<T>> make_moving_factory(T&& value)
{
  return moving_factory<decay_t<T>>(std::forward<T>(value));
}

// a zip_factory is a type of Factory which takes a list of Factories
// and creates a tuple whose elements are the results of the given Factories
template<class... Factories>
struct zip_factory
{
  tuple<Factories...> factory_tuple_;

  __AGENCY_ANNOTATION
  zip_factory(const tuple<Factories...>& factories) : factory_tuple_(factories) {}

  template<size_t... Indices>
  __AGENCY_ANNOTATION
  agency::detail::tuple<
    result_of_factory_t<Factories>...
  >
    impl(agency::detail::index_sequence<Indices...>)
  {
    return agency::detail::make_tuple(detail::get<Indices>(factory_tuple_)()...);
  }

  __AGENCY_ANNOTATION
  agency::detail::tuple<
    result_of_factory_t<Factories>...
  >
    operator()()
  {
    return impl(index_sequence_for<Factories...>());
  }
};

template<class... Factories>
__AGENCY_ANNOTATION
zip_factory<Factories...> make_zip_factory(const tuple<Factories...>& factory_tuple)
{
  return zip_factory<Factories...>(factory_tuple);
}

} // end detail
} // end agency

<|endoftext|>


<commit_before><commit_msg>Update Question 11<commit_after><|endoftext|>


<commit_before>#include <vector>

using re2jit::debug;

static inline void *_compile(re2::Prog *prog)
{
    debug::write("re2jit::it: vm mode\n");
    return prog;
}

static inline void _destroy(void *)
{
}

static inline rejit_entry_t _entry(void *prog)
{
    // When in VM mode, entry points are
    return (rejit_entry_t) ((re2::Prog *) prog)->start();
}

#define BIT_INDEX(x, i) (i / (sizeof((x)[0]) * 8))
#define BIT_SHIFT(x, i) (i % (sizeof((x)[0]) * 8))
#define BIT_GET(x, i) ((x)[BIT_INDEX(x, i)] & (1LL << BIT_SHIFT(x, i)))
#define BIT_SET(x, i) ((x)[BIT_INDEX(x, i)] |= 1LL << BIT_SHIFT(x, i))

static inline bool _run(void *prog, struct rejit_threadset_t *nfa)
{
    re2::Prog *_prog = (re2::Prog *) prog;
    re2::Prog::Inst *op;
    ssize_t stack[256];
    ssize_t stkid = 0;
    size_t  visited_size = (_prog->size() + sizeof(size_t) * 8 - 1) / (sizeof(size_t) * 8);
    size_t *visited = new size_t[visited_size];
    int *capture;

    while (rejit_thread_dispatch(nfa, 1)) {
        stkid = 0;
        stack[stkid++] = (ssize_t) nfa->running->entry;
        capture = nfa->running->groups;

        memset(visited, 0, sizeof(size_t) * visited_size);

        while (stkid--) {
            if (BIT_GET(visited, stack[stkid])) {
                continue;
            }

            BIT_SET(visited, stack[stkid]);
            op = _prog->inst(stack[stkid]);

            if (stack[stkid] == _prog->start()) {
                capture[0] = nfa->offset;
            }

            switch (op->opcode()) {
                case re2::kInstAlt:
                    stack[stkid++] = op->out1();
                    stack[stkid++] = op->out();
                    break;

                case re2::kInstAltMatch:
                    debug::write("re2jit::it: can't interpret kInstAltMatch\n");
                    delete[] visited;
                    return 0;

                case re2::kInstByteRange: {
                    char c = nfa->input[0];

                    if (op->foldcase() && 'A' <= c && c <= 'Z') {
                        c += 'a' - 'A';
                    }

                    if (c < op->lo() || c > op->hi()) {
                        break;
                    }

                    rejit_thread_wait(nfa, op->out(), 1);
                    break;
                }

                case re2::kInstCapture:
                    // TODO
                    stack[stkid++] = op->out();
                    break;

                case re2::kInstEmptyWidth:
                    if (!(op->empty() & ~(nfa->empty))) {
                        stack[stkid++] = op->out();
                    }
                    break;

                case re2::kInstNop:
                    stack[stkid++] = op->out();
                    break;

                case re2::kInstMatch:
                    capture[1] = nfa->offset;

                    if (rejit_thread_match(nfa)) {
                        // this match is preferred to whatever is still on stack.
                        stkid = 0;
                    }

                    break;

                case re2::kInstFail:
                    break;

                default:
                    debug::write("re2jit::it: unknown opcode %d\n", op->opcode());
                    delete[] visited;
                    return 0;
            }
        }
    }

    delete[] visited;
    return 1;
}
<commit_msg>Record submatch boundaries.<commit_after>#include <vector>

using re2jit::debug;

static inline void *_compile(re2::Prog *prog)
{
    debug::write("re2jit::it: vm mode\n");
    return prog;
}

static inline void _destroy(void *)
{
}

static inline rejit_entry_t _entry(void *prog)
{
    // When in VM mode, entry points are
    return (rejit_entry_t) ((re2::Prog *) prog)->start();
}

#define BIT_INDEX(x, i) (i / (sizeof((x)[0]) * 8))
#define BIT_SHIFT(x, i) (i % (sizeof((x)[0]) * 8))
#define BIT_GET(x, i) ((x)[BIT_INDEX(x, i)] & (1LL << BIT_SHIFT(x, i)))
#define BIT_SET(x, i) ((x)[BIT_INDEX(x, i)] |= 1LL << BIT_SHIFT(x, i))

static inline bool _run(void *prog, struct rejit_threadset_t *nfa)
{
    re2::Prog *_prog = (re2::Prog *) prog;
    re2::Prog::Inst *op;
    ssize_t stack[256];
    ssize_t stkid = 0;
    size_t  visited_size = (_prog->size() + sizeof(size_t) * 8 - 1) / (sizeof(size_t) * 8);
    size_t *visited = new size_t[visited_size];
    int *capture;

    while (rejit_thread_dispatch(nfa, 1)) {
        stkid = 0;
        stack[stkid++] = (ssize_t) nfa->running->entry;
        capture = nfa->running->groups;

        while (stkid--) {
            if (BIT_GET(visited, stack[stkid])) {
                continue;
            }

            BIT_SET(visited, stack[stkid]);
            op = _prog->inst(stack[stkid]);

            if (stack[stkid] == _prog->start()) {
                capture[0] = nfa->offset;
            }

            switch (op->opcode()) {
                case re2::kInstAlt:
                    stack[stkid++] = op->out1();
                    stack[stkid++] = op->out();
                    break;

                case re2::kInstAltMatch:
                    debug::write("re2jit::it: can't interpret kInstAltMatch\n");
                    delete[] visited;
                    return 0;

                case re2::kInstByteRange: {
                    if (!nfa->length) {
                        break;
                    }

                    char c = nfa->input[0];

                    if (op->foldcase() && 'A' <= c && c <= 'Z') {
                        c += 'a' - 'A';
                    }

                    if (c < op->lo() || c > op->hi()) {
                        break;
                    }

                    rejit_thread_wait(nfa, op->out(), 1);
                    break;
                }

                case re2::kInstCapture:
                    if ((size_t) op->cap() < nfa->groups) {
                        capture[op->cap()] = nfa->offset;
                    }

                    stack[stkid++] = op->out();
                    break;

                case re2::kInstEmptyWidth:
                    if (!(op->empty() & ~(nfa->empty))) {
                        stack[stkid++] = op->out();
                    }
                    break;

                case re2::kInstNop:
                    stack[stkid++] = op->out();
                    break;

                case re2::kInstMatch:
                    capture[1] = nfa->offset;

                    if (rejit_thread_match(nfa)) {
                        // this match is preferred to whatever is still on stack.
                        stkid = 0;
                    }

                    break;

                case re2::kInstFail:
                    break;

                default:
                    debug::write("re2jit::it: unknown opcode %d\n", op->opcode());
                    delete[] visited;
                    return 0;
            }
        }

        if (nfa->queues[nfa->active_queue].first == rejit_list_end(&nfa->queues[nfa->active_queue])) {
            // this bit vector is shared across all threads on a single queue.
            // whichever thread first enters a state gets to own that state.
            memset(visited, 0, sizeof(size_t) * visited_size);
        }
    }

    delete[] visited;
    return 1;
}
<|endoftext|>


<commit_before>#include "ghost/crs_kacz.h"
#include "ghost/crs.h"
#include "ghost/complex.h"
#include "ghost/locality.h"
#include <complex>

template<typename m_t, typename v_t, bool forward>
static ghost_error_t crs_kacz(ghost_sparsemat_t *mat, ghost_densemat_t *x, ghost_densemat_t *b, v_t *omega)
{
    if (!mat->color_ptr || mat->ncolors == 0) {
        WARNING_LOG("Matrix has not been colored!");
    }

    ghost_lidx_t i;
    ghost_lidx_t row;
    ghost_lidx_t j;
    ghost_lidx_t color;
    ghost_crs_t *crmat = CR(mat);
    v_t *bval = (v_t *)(b->val[0]);
    v_t *xval = (v_t *)(x->val[0]);
    m_t *mval = (m_t *)crmat->val;
    m_t rownorm;

    int rank;
    ghost_rank(&rank,mat->context->mpicomm);

    ghost_lidx_t firstcolor, lastcolor, stride;

    if (forward) {
        firstcolor = 0;
        lastcolor = mat->ncolors;
        stride = 1;
    } else {
        firstcolor = mat->ncolors-1;
        lastcolor = -1;
        stride = -1;
    }

    for (color=firstcolor; color!=lastcolor; color+=stride) {
#pragma omp parallel for private(i,j,row,rownorm)
        for (i=mat->color_ptr[color]; i<mat->color_ptr[color+1]; i++) {
            row = i;
            rownorm = 0.;
            v_t scal = -bval[row];

            for (j=crmat->rpt[row]; j<crmat->rpt[row+1]; j++) {
                scal += (v_t)mval[j] * xval[crmat->col[j]];
                rownorm += mval[j]*mval[j];
            }

            scal /= (v_t)rownorm;

            for (j=crmat->rpt[row]; j<crmat->rpt[row+1]; j++) {
                xval[crmat->col[j]] = xval[crmat->col[j]] - (*omega) * scal * (v_t)mval[j];
            }
        }
    }

    return GHOST_SUCCESS;
}

ghost_error_t ghost_crs_kacz(ghost_sparsemat_t *mat, ghost_densemat_t *lhs, ghost_densemat_t *rhs, void *omega, int forward)
{
    if (mat->traits->datatype != lhs->traits.datatype || lhs->traits.datatype != rhs->traits.datatype) {
        WARNING_LOG("Mixed data types not yet implemented!");
    }

    if (rhs->traits.datatype & GHOST_DT_COMPLEX) {
        if (rhs->traits.datatype & GHOST_DT_DOUBLE) {
            if (forward) {
                return crs_kacz<std::complex<double>, std::complex<double>, true>(mat,lhs,rhs,(std::complex<double> *)omega);
            } else {
                return crs_kacz<std::complex<double>, std::complex<double>, false>(mat,lhs,rhs,(std::complex<double> *)omega);
            }
        } else {
            if (forward) {
                return crs_kacz<std::complex<float>, std::complex<float>, true>(mat,lhs,rhs,(std::complex<float> *)omega);
            } else {
                return crs_kacz<std::complex<float>, std::complex<float>, false>(mat,lhs,rhs,(std::complex<float> *)omega);
            }
        }
    } else {
        if (rhs->traits.datatype & GHOST_DT_DOUBLE) {
            if (forward) {
                return crs_kacz<double, double, true>(mat,lhs,rhs,(double *)omega);
            } else {
                return crs_kacz<double, double, false>(mat,lhs,rhs,(double *)omega);
            }
        } else {
            if (forward) {
                return crs_kacz<float, float, true>(mat,lhs,rhs,(float *)omega);
            } else {
                return crs_kacz<float, float, false>(mat,lhs,rhs,(float *)omega);
            }
        }
    }
}
<commit_msg>check for multivec<commit_after>#include "ghost/crs_kacz.h"
#include "ghost/crs.h"
#include "ghost/complex.h"
#include "ghost/locality.h"
#include <complex>

template<typename m_t, typename v_t, bool forward>
static ghost_error_t crs_kacz(ghost_sparsemat_t *mat, ghost_densemat_t *x, ghost_densemat_t *b, v_t *omega)
{
    if (!mat->color_ptr || mat->ncolors == 0) {
        WARNING_LOG("Matrix has not been colored!");
    }
    if (x->traits.ncols > 1) {
        ERROR_LOG("Multi-vec not implemented!");
        return GHOST_ERR_NOT_IMPLEMENTED;
    }

    ghost_lidx_t i;
    ghost_lidx_t row;
    ghost_lidx_t j;
    ghost_lidx_t color;
    ghost_crs_t *crmat = CR(mat);
    v_t *bval = (v_t *)(b->val[0]);
    v_t *xval = (v_t *)(x->val[0]);
    m_t *mval = (m_t *)crmat->val;
    m_t rownorm;

    int rank;
    ghost_rank(&rank,mat->context->mpicomm);

    ghost_lidx_t firstcolor, lastcolor, stride;

    if (forward) {
        firstcolor = 0;
        lastcolor = mat->ncolors;
        stride = 1;
    } else {
        firstcolor = mat->ncolors-1;
        lastcolor = -1;
        stride = -1;
    }

    for (color=firstcolor; color!=lastcolor; color+=stride) {
#pragma omp parallel for private(i,j,row,rownorm)
        for (i=mat->color_ptr[color]; i<mat->color_ptr[color+1]; i++) {
            row = i;
            rownorm = 0.;
            v_t scal = -bval[row];

            for (j=crmat->rpt[row]; j<crmat->rpt[row+1]; j++) {
                scal += (v_t)mval[j] * xval[crmat->col[j]];
                rownorm += mval[j]*mval[j];
            }

            scal /= (v_t)rownorm;

            for (j=crmat->rpt[row]; j<crmat->rpt[row+1]; j++) {
                xval[crmat->col[j]] = xval[crmat->col[j]] - (*omega) * scal * (v_t)mval[j];
            }
        }
    }

    return GHOST_SUCCESS;
}

ghost_error_t ghost_crs_kacz(ghost_sparsemat_t *mat, ghost_densemat_t *lhs, ghost_densemat_t *rhs, void *omega, int forward)
{
    if (mat->traits->datatype != lhs->traits.datatype || lhs->traits.datatype != rhs->traits.datatype) {
        WARNING_LOG("Mixed data types not yet implemented!");
    }

    if (rhs->traits.datatype & GHOST_DT_COMPLEX) {
        if (rhs->traits.datatype & GHOST_DT_DOUBLE) {
            if (forward) {
                return crs_kacz<std::complex<double>, std::complex<double>, true>(mat,lhs,rhs,(std::complex<double> *)omega);
            } else {
                return crs_kacz<std::complex<double>, std::complex<double>, false>(mat,lhs,rhs,(std::complex<double> *)omega);
            }
        } else {
            if (forward) {
                return crs_kacz<std::complex<float>, std::complex<float>, true>(mat,lhs,rhs,(std::complex<float> *)omega);
            } else {
                return crs_kacz<std::complex<float>, std::complex<float>, false>(mat,lhs,rhs,(std::complex<float> *)omega);
            }
        }
    } else {
        if (rhs->traits.datatype & GHOST_DT_DOUBLE) {
            if (forward) {
                return crs_kacz<double, double, true>(mat,lhs,rhs,(double *)omega);
            } else {
                return crs_kacz<double, double, false>(mat,lhs,rhs,(double *)omega);
            }
        } else {
            if (forward) {
                return crs_kacz<float, float, true>(mat,lhs,rhs,(float *)omega);
            } else {
                return crs_kacz<float, float, false>(mat,lhs,rhs,(float *)omega);
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
===============================================================================

  FILE:  crscheck.hpp

  CONTENTS:

    Functions to validate whether the GEOTIFF tags specify a valid geo-coding
    and (someday) whether they are in agreement to the OGC WKT string.

  PROGRAMMERS:

    martin.isenburg@rapidlasso.com  -  http://rapidlasso.com

  COPYRIGHT:

    (c) 2007-2015, martin isenburg, rapidlasso - tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING.txt file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    8 July 2015 -- look-up name of unknown ESPG codes in list by Loren Dawe
    3 July 2014 -- allowing unknown ESPG codes to pass CRS check with warning
    8 September 2013 -- it started raining on the beach after TREEMAPS meeting

===============================================================================
*/
#ifndef CRS_CHECK_HPP
#define CRS_CHECK_HPP

#include "lasheader.hpp"

class CRSprojectionEllipsoid
{
public:
  I32 id;
  const CHAR* name;
  F64 equatorial_radius;
  F64 polar_radius;
  F64 eccentricity_squared;
  F64 inverse_flattening;
  F64 eccentricity_prime_squared;
  F64 eccentricity;
  F64 eccentricity_e1;
};

class CRSprojectionParameters
{
public:
  I32 type;
  CHAR name[256];
  I16 geokey;
  CRSprojectionParameters() { type = -1; memset(name, 0, 256); geokey = 0; };
};

class CRSprojectionParametersUTM : public CRSprojectionParameters
{
public:
  I32 utm_zone_number;
  CHAR utm_zone_letter;
  BOOL utm_northern_hemisphere;
  I32 utm_long_origin;
};

class CRSprojectionParametersLCC : public CRSprojectionParameters
{
public:
  F64 lcc_false_easting_meter;
  F64 lcc_false_northing_meter;
  F64 lcc_lat_origin_degree;
  F64 lcc_long_meridian_degree;
  F64 lcc_first_std_parallel_degree;
  F64 lcc_second_std_parallel_degree;
  F64 lcc_lat_origin_radian;
  F64 lcc_long_meridian_radian;
  F64 lcc_first_std_parallel_radian;
  F64 lcc_second_std_parallel_radian;
  F64 lcc_n;
  F64 lcc_aF;
  F64 lcc_rho0;
};

class CRSprojectionParametersTM : public CRSprojectionParameters
{
public:
  F64 tm_false_easting_meter;
  F64 tm_false_northing_meter;
  F64 tm_lat_origin_degree;
  F64 tm_long_meridian_degree;
  F64 tm_scale_factor;
  F64 tm_lat_origin_radian;
  F64 tm_long_meridian_radian;
  F64 tm_ap;
  F64 tm_bp;
  F64 tm_cp;
  F64 tm_dp;
  F64 tm_ep;
};

class CRScheck
{
public:
  void check(LASheader* lasheader, CHAR* description=0, BOOL no_CRS_fail=FALSE);
  CRScheck();
  ~CRScheck();

private:
  U32 coordinate_units[2];
  U32 elevation_units[2];
  U32 vertical_epsg[2];
  CRSprojectionEllipsoid* ellipsoids[2];
  CRSprojectionParameters* projections[2];

  void set_coordinates_in_survey_feet(const BOOL from_geokeys);
  void set_coordinates_in_feet(const BOOL from_geokeys);
  void set_coordinates_in_meter(const BOOL from_geokeys);
  void set_elevation_in_survey_feet(const BOOL from_geokeys);
  void set_elevation_in_feet(const BOOL from_geokeys);
  void set_elevation_in_meter(const BOOL from_geokeys);
  BOOL set_ellipsoid(const I32 ellipsoid_id, const BOOL from_geokeys, char* description=0);
  void set_projection(CRSprojectionParameters* projection, const BOOL from_geokeys);
  BOOL set_no_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_latlong_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_longlat_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_ecef_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_utm_projection(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_utm_projection(const I32 zone, const BOOL northern, const const BOOL from_geokeys, CHAR* description=0);
  BOOL set_mga_projection(const I32 zone, const BOOL northern, const const BOOL from_geokeys, CHAR* description=0);
  void set_lambert_conformal_conic_projection(const F64 falseEasting, const F64 falseNorthing, const F64 latOriginDegree, const F64 longMeridianDegree, const F64 firstStdParallelDegree, const F64 secondStdParallelDegree, const BOOL from_geokeys, CHAR* description=0);
  void set_transverse_mercator_projection(const F64 falseEasting, const F64 falseNorthing, const F64 latOriginDegree, const F64 longMeridianDegree, const F64 scaleFactor, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad27_lcc(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad83_lcc(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad27_tm(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad83_tm(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_coordinates_from_ProjLinearUnitsGeoKey(U16 value);
  BOOL set_elevation_from_VerticalUnitsGeoKey(U16 value);
  BOOL set_vertical_from_VerticalCSTypeGeoKey(U16 value);
  BOOL set_projection_from_ProjectedCSTypeGeoKey(const U16 value, CHAR* description=0);

  BOOL check_geokeys(LASheader* lasheader, CHAR* description);
};

#endif
<commit_msg>remove double const<commit_after>/*
===============================================================================

  FILE:  crscheck.hpp

  CONTENTS:

    Functions to validate whether the GEOTIFF tags specify a valid geo-coding
    and (someday) whether they are in agreement to the OGC WKT string.

  PROGRAMMERS:

    martin.isenburg@rapidlasso.com  -  http://rapidlasso.com

  COPYRIGHT:

    (c) 2007-2015, martin isenburg, rapidlasso - tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING.txt file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    8 July 2015 -- look-up name of unknown ESPG codes in list by Loren Dawe
    3 July 2014 -- allowing unknown ESPG codes to pass CRS check with warning
    8 September 2013 -- it started raining on the beach after TREEMAPS meeting

===============================================================================
*/
#ifndef CRS_CHECK_HPP
#define CRS_CHECK_HPP

#include "lasheader.hpp"

class CRSprojectionEllipsoid
{
public:
  I32 id;
  const CHAR* name;
  F64 equatorial_radius;
  F64 polar_radius;
  F64 eccentricity_squared;
  F64 inverse_flattening;
  F64 eccentricity_prime_squared;
  F64 eccentricity;
  F64 eccentricity_e1;
};

class CRSprojectionParameters
{
public:
  I32 type;
  CHAR name[256];
  I16 geokey;
  CRSprojectionParameters() { type = -1; memset(name, 0, 256); geokey = 0; };
};

class CRSprojectionParametersUTM : public CRSprojectionParameters
{
public:
  I32 utm_zone_number;
  CHAR utm_zone_letter;
  BOOL utm_northern_hemisphere;
  I32 utm_long_origin;
};

class CRSprojectionParametersLCC : public CRSprojectionParameters
{
public:
  F64 lcc_false_easting_meter;
  F64 lcc_false_northing_meter;
  F64 lcc_lat_origin_degree;
  F64 lcc_long_meridian_degree;
  F64 lcc_first_std_parallel_degree;
  F64 lcc_second_std_parallel_degree;
  F64 lcc_lat_origin_radian;
  F64 lcc_long_meridian_radian;
  F64 lcc_first_std_parallel_radian;
  F64 lcc_second_std_parallel_radian;
  F64 lcc_n;
  F64 lcc_aF;
  F64 lcc_rho0;
};

class CRSprojectionParametersTM : public CRSprojectionParameters
{
public:
  F64 tm_false_easting_meter;
  F64 tm_false_northing_meter;
  F64 tm_lat_origin_degree;
  F64 tm_long_meridian_degree;
  F64 tm_scale_factor;
  F64 tm_lat_origin_radian;
  F64 tm_long_meridian_radian;
  F64 tm_ap;
  F64 tm_bp;
  F64 tm_cp;
  F64 tm_dp;
  F64 tm_ep;
};

class CRScheck
{
public:
  void check(LASheader* lasheader, CHAR* description=0, BOOL no_CRS_fail=FALSE);
  CRScheck();
  ~CRScheck();

private:
  U32 coordinate_units[2];
  U32 elevation_units[2];
  U32 vertical_epsg[2];
  CRSprojectionEllipsoid* ellipsoids[2];
  CRSprojectionParameters* projections[2];

  void set_coordinates_in_survey_feet(const BOOL from_geokeys);
  void set_coordinates_in_feet(const BOOL from_geokeys);
  void set_coordinates_in_meter(const BOOL from_geokeys);
  void set_elevation_in_survey_feet(const BOOL from_geokeys);
  void set_elevation_in_feet(const BOOL from_geokeys);
  void set_elevation_in_meter(const BOOL from_geokeys);
  BOOL set_ellipsoid(const I32 ellipsoid_id, const BOOL from_geokeys, char* description=0);
  void set_projection(CRSprojectionParameters* projection, const BOOL from_geokeys);
  BOOL set_no_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_latlong_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_longlat_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_ecef_projection(const BOOL from_geokeys, CHAR* description=0);
  BOOL set_utm_projection(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_utm_projection(const I32 zone, const BOOL northern, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_mga_projection(const I32 zone, const BOOL northern, const BOOL from_geokeys, CHAR* description=0);
  void set_lambert_conformal_conic_projection(const F64 falseEasting, const F64 falseNorthing, const F64 latOriginDegree, const F64 longMeridianDegree, const F64 firstStdParallelDegree, const F64 secondStdParallelDegree, const BOOL from_geokeys, CHAR* description=0);
  void set_transverse_mercator_projection(const F64 falseEasting, const F64 falseNorthing, const F64 latOriginDegree, const F64 longMeridianDegree, const F64 scaleFactor, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad27_lcc(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad83_lcc(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad27_tm(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_state_plane_nad83_tm(const CHAR* zone, const BOOL from_geokeys, CHAR* description=0);
  BOOL set_coordinates_from_ProjLinearUnitsGeoKey(U16 value);
  BOOL set_elevation_from_VerticalUnitsGeoKey(U16 value);
  BOOL set_vertical_from_VerticalCSTypeGeoKey(U16 value);
  BOOL set_projection_from_ProjectedCSTypeGeoKey(const U16 value, CHAR* description=0);

  BOOL check_geokeys(LASheader* lasheader, CHAR* description);
};

#endif
<|endoftext|>


<commit_before>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "Benchmark.h"
#include "ContextSearchBm.h"
#include "DispatchQueueBm.h"
#include "PrintableDuration.h"
#include "PriorityBoost.h"
#include <map>
#include <iomanip>
#include <iostream>
#include <string>

Benchmark PrintUsage(void);

struct Entry {
  bool utility = false;
  const char* name = nullptr;
  const char* desc = nullptr;
  Benchmark(*pfn)() = nullptr;
};

std::pair<std::string, Entry> MakeEntry(const char* name, const char* desc, Benchmark(*pfn)()) {
  Entry retVal;
  retVal.name = name;
  retVal.desc = desc;
  retVal.pfn = pfn;
  return std::make_pair(name, retVal);
}

std::pair<std::string, Entry> MakeUtilEntry(const char* name, const char* desc, Benchmark(*pfn)()) {
  auto retVal = MakeEntry(name, desc, pfn);
  retVal.second.utility = true;
  return retVal;
}

static Benchmark All(void);

static std::map<std::string, Entry> sc_commands = {
  MakeUtilEntry("help", "Displays this information", &PrintUsage),
  MakeUtilEntry("all", "Runs all benchmarks", &All),
  MakeEntry("priority", "Thread priority boost behavior", &PriorityBoost::CanBoostPriority),
  MakeEntry("search", "Autowiring context search cost", &ContextSearchBm::Search),
  MakeEntry("cache", "Autowiring cache behavior", &ContextSearchBm::Cache),
  MakeEntry("fast", "Autowired versus AutowiredFast", &ContextSearchBm::Fast),
  MakeEntry("dispatch", "Dispatch queue execution rate", &DispatchQueueBm::Dispatch)
};

static Benchmark All(void) {
  for (auto& command : sc_commands) {
    // Skip commands that are just utility:
    if (command.second.utility)
      continue;

    Benchmark bm = command.second.pfn();
    std::cout
      << command.first << std::endl
      << bm << std::endl;
  }

  // Empty benchmark, causes the parent to avoid printing this out:
  return Benchmark{};
}

Benchmark PrintUsage(void) {
  std::cout
    << "Usage: AutoBench <command>" << std::endl
    << "Supported commands:" << std::endl
    << std::endl;

  for (auto& command : sc_commands)
    std::cout << " " << std::setw(12) << std::left << command.first << command.second.desc << std::endl;
  return Benchmark{};
}

int main(int argc, const char* argv[]) {
  switch (argc) {
  default:
    PrintUsage();
    return -1;
  case 2:
    auto& cur = sc_commands[argv[1]];
    if (!cur.name) {
      std::cerr << "Unrecognized command" << std::endl;
      PrintUsage();
      return -1;
    }

    try {
      Benchmark benchmark = cur.pfn();
      if (!cur.utility)
        std::cout << benchmark;
    }
    catch (std::exception& ex) {
      std::cerr << ex.what() << std::endl;
      return -1;
    }
  }
  return 0;
}
<commit_msg>Teach AutoBench how to accept multiple benchmarks<commit_after>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "Benchmark.h"
#include "ContextSearchBm.h"
#include "DispatchQueueBm.h"
#include "PrintableDuration.h"
#include "PriorityBoost.h"
#include <map>
#include <iomanip>
#include <iostream>
#include <string>

Benchmark PrintUsage(void);

struct Entry {
  bool utility = false;
  const char* name = nullptr;
  const char* desc = nullptr;
  Benchmark(*pfn)() = nullptr;
};

std::pair<std::string, Entry> MakeEntry(const char* name, const char* desc, Benchmark(*pfn)()) {
  Entry retVal;
  retVal.name = name;
  retVal.desc = desc;
  retVal.pfn = pfn;
  return std::make_pair(name, retVal);
}

std::pair<std::string, Entry> MakeUtilEntry(const char* name, const char* desc, Benchmark(*pfn)()) {
  auto retVal = MakeEntry(name, desc, pfn);
  retVal.second.utility = true;
  return retVal;
}

static Benchmark All(void);

static std::map<std::string, Entry> sc_commands = {
  MakeUtilEntry("help", "Displays this information", &PrintUsage),
  MakeUtilEntry("all", "Runs all benchmarks", &All),
  MakeEntry("priority", "Thread priority boost behavior", &PriorityBoost::CanBoostPriority),
  MakeEntry("search", "Autowiring context search cost", &ContextSearchBm::Search),
  MakeEntry("cache", "Autowiring cache behavior", &ContextSearchBm::Cache),
  MakeEntry("fast", "Autowired versus AutowiredFast", &ContextSearchBm::Fast),
  MakeEntry("dispatch", "Dispatch queue execution rate", &DispatchQueueBm::Dispatch)
};

static Benchmark All(void) {
  for (auto& command : sc_commands) {
    // Skip commands that are just utility:
    if (command.second.utility)
      continue;

    Benchmark bm = command.second.pfn();
    std::cout
      << command.first << std::endl
      << bm << std::endl;
  }

  // Empty benchmark, causes the parent to avoid printing this out:
  return Benchmark{};
}

Benchmark PrintUsage(void) {
  std::cout
    << "Usage: AutoBench <command>" << std::endl
    << "Supported commands:" << std::endl
    << std::endl;

  for (auto& command : sc_commands)
    std::cout << " " << std::setw(12) << std::left << command.first << command.second.desc << std::endl;
  return Benchmark{};
}

int main(int argc, const char* argv[]) {
  if (argc <= 1) {
    PrintUsage();
    return -1;
  }

  // First pass, ensure we recognize all commands:
  for (int i = 1; i < argc; i++)
    if (!sc_commands[argv[i]].name) {
      std::cerr << "Unrecognized command" << std::endl;
      PrintUsage();
      return -1;
    }

  // Now execute everything:
  bool errors = false;
  for (int i = 1; i < argc; i++) {
    auto& cur = sc_commands[argv[i]];
    try {
      Benchmark benchmark = cur.pfn();
      if (!cur.utility)
        std::cout
          << cur.name << std::endl
          << benchmark << std::endl;
    }
    catch (std::exception& ex) {
      std::cerr << ex.what() << std::endl;
      errors = true;
    }
  }
  return errors ? -1 : 0;
}
<|endoftext|>


<commit_before>// Copyright 2017 The NXT Authors
//
// 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 "backend/vulkan/CommandBufferVk.h"

#include "backend/Commands.h"
#include "backend/vulkan/BufferVk.h"
#include "backend/vulkan/TextureVk.h"
#include "backend/vulkan/VulkanBackend.h"

namespace backend { namespace vulkan {

    namespace {

        VkBufferImageCopy ComputeBufferImageCopyRegion(uint32_t rowPitch,
                                                       const BufferCopyLocation& bufferLocation,
                                                       const TextureCopyLocation& textureLocation) {
            const Texture* texture = ToBackend(textureLocation.texture).Get();

            VkBufferImageCopy region;

            region.bufferOffset = bufferLocation.offset;
            // In Vulkan the row length is in texels while it is in bytes for NXT
            region.bufferRowLength = rowPitch / TextureFormatPixelSize(texture->GetFormat());
            region.bufferImageHeight = rowPitch * textureLocation.height;

            region.imageSubresource.aspectMask = texture->GetVkAspectMask();
            region.imageSubresource.mipLevel = textureLocation.level;
            region.imageSubresource.baseArrayLayer = 0;
            region.imageSubresource.layerCount = 1;

            region.imageOffset.x = textureLocation.x;
            region.imageOffset.y = textureLocation.y;
            region.imageOffset.z = textureLocation.z;

            region.imageExtent.width = textureLocation.width;
            region.imageExtent.height = textureLocation.height;
            region.imageExtent.depth = textureLocation.depth;

            return region;
        }

    }  // anonymous namespace

    CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
        : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) {
    }

    CommandBuffer::~CommandBuffer() {
        FreeCommands(&mCommands);
    }

    void CommandBuffer::RecordCommands(VkCommandBuffer commands) {
        Device* device = ToBackend(GetDevice());

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::CopyBufferToBuffer: {
                    CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkBufferCopy region;
                    region.srcOffset = src.offset;
                    region.dstOffset = dst.offset;
                    region.size = copy->size;

                    VkBuffer srcHandle = ToBackend(src.buffer)->GetHandle();
                    VkBuffer dstHandle = ToBackend(dst.buffer)->GetHandle();
                    device->fn.CmdCopyBuffer(commands, srcHandle, dstHandle, 1, &region);
                } break;

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
                    VkImage dstImage = ToBackend(dst.texture)->GetHandle();
                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(copy->rowPitch, src, dst);

                    // The image is written to so the NXT guarantees make sure it is in the
                    // TRANSFER_DST_OPTIMAL layout
                    device->fn.CmdCopyBufferToImage(commands, srcBuffer, dstImage,
                                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
                                                    &region);
                } break;

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkImage srcImage = ToBackend(src.texture)->GetHandle();
                    VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(copy->rowPitch, dst, src);

                    // The NXT TransferSrc usage is always mapped to GENERAL
                    device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
                                                    dstBuffer, 1, &region);
                } break;

                case Command::TransitionBufferUsage: {
                    TransitionBufferUsageCmd* cmd =
                        mCommands.NextCommand<TransitionBufferUsageCmd>();

                    Buffer* buffer = ToBackend(cmd->buffer.Get());
                    buffer->RecordBarrier(commands, buffer->GetUsage(), cmd->usage);
                    buffer->UpdateUsageInternal(cmd->usage);
                } break;

                case Command::TransitionTextureUsage: {
                    TransitionTextureUsageCmd* cmd =
                        mCommands.NextCommand<TransitionTextureUsageCmd>();

                    Texture* texture = ToBackend(cmd->texture.Get());
                    texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage);
                    texture->UpdateUsageInternal(cmd->usage);
                } break;

                default: { UNREACHABLE(); } break;
            }
        }
    }

}}  // namespace backend::vulkan
<commit_msg>Vulkan: Implement Set[Index|Vertex]Buffers<commit_after>// Copyright 2017 The NXT Authors
//
// 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 "backend/vulkan/CommandBufferVk.h"

#include "backend/Commands.h"
#include "backend/vulkan/BufferVk.h"
#include "backend/vulkan/TextureVk.h"
#include "backend/vulkan/VulkanBackend.h"

namespace backend { namespace vulkan {

    namespace {

        VkBufferImageCopy ComputeBufferImageCopyRegion(uint32_t rowPitch,
                                                       const BufferCopyLocation& bufferLocation,
                                                       const TextureCopyLocation& textureLocation) {
            const Texture* texture = ToBackend(textureLocation.texture).Get();

            VkBufferImageCopy region;

            region.bufferOffset = bufferLocation.offset;
            // In Vulkan the row length is in texels while it is in bytes for NXT
            region.bufferRowLength = rowPitch / TextureFormatPixelSize(texture->GetFormat());
            region.bufferImageHeight = rowPitch * textureLocation.height;

            region.imageSubresource.aspectMask = texture->GetVkAspectMask();
            region.imageSubresource.mipLevel = textureLocation.level;
            region.imageSubresource.baseArrayLayer = 0;
            region.imageSubresource.layerCount = 1;

            region.imageOffset.x = textureLocation.x;
            region.imageOffset.y = textureLocation.y;
            region.imageOffset.z = textureLocation.z;

            region.imageExtent.width = textureLocation.width;
            region.imageExtent.height = textureLocation.height;
            region.imageExtent.depth = textureLocation.depth;

            return region;
        }

    }  // anonymous namespace

    CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
        : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) {
    }

    CommandBuffer::~CommandBuffer() {
        FreeCommands(&mCommands);
    }

    void CommandBuffer::RecordCommands(VkCommandBuffer commands) {
        Device* device = ToBackend(GetDevice());

        Command type;
        while (mCommands.NextCommandId(&type)) {
            switch (type) {
                case Command::CopyBufferToBuffer: {
                    CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkBufferCopy region;
                    region.srcOffset = src.offset;
                    region.dstOffset = dst.offset;
                    region.size = copy->size;

                    VkBuffer srcHandle = ToBackend(src.buffer)->GetHandle();
                    VkBuffer dstHandle = ToBackend(dst.buffer)->GetHandle();
                    device->fn.CmdCopyBuffer(commands, srcHandle, dstHandle, 1, &region);
                } break;

                case Command::CopyBufferToTexture: {
                    CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
                    VkImage dstImage = ToBackend(dst.texture)->GetHandle();
                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(copy->rowPitch, src, dst);

                    // The image is written to so the NXT guarantees make sure it is in the
                    // TRANSFER_DST_OPTIMAL layout
                    device->fn.CmdCopyBufferToImage(commands, srcBuffer, dstImage,
                                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
                                                    &region);
                } break;

                case Command::CopyTextureToBuffer: {
                    CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
                    auto& src = copy->source;
                    auto& dst = copy->destination;

                    VkImage srcImage = ToBackend(src.texture)->GetHandle();
                    VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
                    VkBufferImageCopy region =
                        ComputeBufferImageCopyRegion(copy->rowPitch, dst, src);

                    // The NXT TransferSrc usage is always mapped to GENERAL
                    device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
                                                    dstBuffer, 1, &region);
                } break;

                case Command::SetIndexBuffer: {
                    SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
                    VkBuffer indexBuffer = ToBackend(cmd->buffer)->GetHandle();

                    // TODO(cwallez@chromium.org): get the index type from the last render pipeline
                    // and rebind if needed on pipeline change
                    device->fn.CmdBindIndexBuffer(commands, indexBuffer,
                                                  static_cast<VkDeviceSize>(cmd->offset),
                                                  VK_INDEX_TYPE_UINT16);
                } break;

                case Command::SetVertexBuffers: {
                    SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
                    auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
                    auto offsets = mCommands.NextData<uint32_t>(cmd->count);

                    std::array<VkBuffer, kMaxVertexInputs> vkBuffers;
                    std::array<VkDeviceSize, kMaxVertexInputs> vkOffsets;

                    for (uint32_t i = 0; i < cmd->count; ++i) {
                        Buffer* buffer = ToBackend(buffers[i].Get());
                        vkBuffers[i] = buffer->GetHandle();
                        vkOffsets[i] = static_cast<VkDeviceSize>(offsets[i]);
                    }

                    device->fn.CmdBindVertexBuffers(commands, cmd->startSlot, cmd->count,
                                                    vkBuffers.data(), vkOffsets.data());
                } break;

                case Command::TransitionBufferUsage: {
                    TransitionBufferUsageCmd* cmd =
                        mCommands.NextCommand<TransitionBufferUsageCmd>();

                    Buffer* buffer = ToBackend(cmd->buffer.Get());
                    buffer->RecordBarrier(commands, buffer->GetUsage(), cmd->usage);
                    buffer->UpdateUsageInternal(cmd->usage);
                } break;

                case Command::TransitionTextureUsage: {
                    TransitionTextureUsageCmd* cmd =
                        mCommands.NextCommand<TransitionTextureUsageCmd>();

                    Texture* texture = ToBackend(cmd->texture.Get());
                    texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage);
                    texture->UpdateUsageInternal(cmd->usage);
                } break;

                default: { UNREACHABLE(); } break;
            }
        }
    }

}}  // namespace backend::vulkan
<|endoftext|>