<commit_before>////////////////////////////////////////////
//  Filename NFCHttpClient.cpp
//  Copyright (C) 2017  Stonexin
//  CreateTime 2017/07/05
//
////////////////////////////////////////////
#include "NFCHttpClient.h"

#if NF_PLATFORM == NF_PLATFORM_WIN
#include <WS2tcpip.h>
#include <winsock2.h>
#pragma  comment(lib,"Ws2_32.lib")
#pragma  comment(lib,"libevent.lib")
#pragma  comment(lib,"libevent_core.lib")

#if NF_ENABLE_SSL
#pragma  comment(lib,"libevent_openssl.lib")
#pragma  comment(lib,"libeay32.lib")
#pragma  comment(lib,"ssleay32.lib")
#endif

#endif

bool NFCHttpClient::Execute()
{
	if (m_pBase)
	{
		event_base_loop(m_pBase, EVLOOP_ONCE | EVLOOP_NONBLOCK);
	}

	return true;
}

bool NFCHttpClient::Init()
{
#if NF_PLATFORM == NF_PLATFORM_WIN
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(2, 2);
	int err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		return false;
	}
#endif
	m_strUserAgent = DEFAULT_USER_AGENT;// strUserAgent;

#if NF_ENABLE_SSL

#if OPENSSL_VERSION_NUMBER < 0x10100000L
	// Initialize OpenSSL
	SSL_library_init();
	ERR_load_crypto_strings();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
#endif

	m_pSslCtx = SSL_CTX_new(SSLv23_client_method());
	if (!m_pSslCtx) {
		printf("SSL_CTX_new err.");
		return false;
	}

#endif

	m_pBase = event_base_new();
	if (m_pBase == nullptr)
	{
		printf("event_base_new err.");
		return false;
	}
	return true;
}

bool NFCHttpClient::Final()
{
	if (m_pBase)
	{
		event_base_free(m_pBase);
		m_pBase = nullptr;
	}

#if NF_ENABLE_SSL
	if (m_pSslCtx)
	{
		SSL_CTX_free(m_pSslCtx);
		m_pSslCtx = nullptr;
	}

#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
	EVP_cleanup();
	ERR_free_strings();

#if OPENSSL_VERSION_NUMBER < 0x10000000L
	ERR_remove_state(0);
#else
	ERR_remove_thread_state(NULL);
#endif

	CRYPTO_cleanup_all_ex_data();

	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) */
#endif
	return true;
}

bool NFCHttpClient::MakeRequest(const std::string& strUri,
	const std::string& strUserData,
	const std::string& strPostData,
	HTTP_RESP_FUNCTOR_PTR pCB,
	bool bPost)
{
	struct evhttp_uri *http_uri = NULL;
	const char *scheme, *host, *path, *query;

	http_uri = evhttp_uri_parse(strUri.c_str());
	if (http_uri == NULL) {
		return false;
	}

	bool isHttps = false;

	scheme = evhttp_uri_get_scheme(http_uri);
	std::string lowwerScheme(scheme);
	std::transform(lowwerScheme.begin(), lowwerScheme.end(), lowwerScheme.begin(), (int(*)(int))std::tolower);
	if (scheme == NULL || (lowwerScheme.compare("https") != 0 && lowwerScheme.compare("http") != 0)) {
		return false;
	}

	if (lowwerScheme.compare("https") == 0)
	{
		isHttps = true;
	}

	host = evhttp_uri_get_host(http_uri);
	if (host == NULL) {
		printf("url must have a host \n");
		return false;
	}

	int port = evhttp_uri_get_port(http_uri);
	if (port == -1) {
		port = isHttps ? 443 : 80;
	}

	path = evhttp_uri_get_path(http_uri);
	if (strlen(path) == 0) {
		path = "/";
	}

	char uri[512] = { 0 };

	query = evhttp_uri_get_query(http_uri);
	if (query == NULL) {
		snprintf(uri, sizeof(uri) - 1, "%s", path);
	}
	else {
		snprintf(uri, sizeof(uri) - 1, "%s?%s", path, query);
	}
	uri[sizeof(uri) - 1] = '\0';

	//-------we do not verify peer--------//
	//like the curl SSL_VERIFYPEER is set false

	//if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
	//	err_openssl("SSL_CTX_load_verify_locations");
	//	goto error;
	//}
	//SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
	//SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback,(void *)host);

	struct bufferevent* bev = NULL;

#if NF_ENABLE_SSL
	SSL *pSSL = SSL_new(m_pSslCtx);
	if (pSSL == NULL) {
		printf("SSL_new err.");
		return false;
	}
#endif

	if (!isHttps) {
		bev = bufferevent_socket_new(m_pBase, -1, BEV_OPT_CLOSE_ON_FREE);
	}
	else {
#if NF_ENABLE_SSL
		bev = bufferevent_openssl_socket_new(m_pBase, -1, pSSL,
			BUFFEREVENT_SSL_CONNECTING,
			BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
#endif
	}

	if (bev == NULL) {
		fprintf(stderr, "bufferevent_socket_new() failed\n");
		return false;
	}

#if NF_ENABLE_SSL
	if (isHttps)
	{
		bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
	}
#endif

	struct evhttp_connection* evcon = evhttp_connection_base_bufferevent_new(m_pBase, NULL, bev, host, port);
	if (evcon == NULL) {
		fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
		return false;
	}

	if (m_nRetry > 0) {
		evhttp_connection_set_retries(evcon, m_nRetry);
	}
	if (m_nTimeOut >= 0) {
		evhttp_connection_set_timeout(evcon, m_nTimeOut);
	}

	HttpObject* pHttpObj = new HttpObject(this, bev, strUserData, pCB);
	pHttpObj->SetUri(strUri);

	// Fire off the request
	struct evhttp_request* req = evhttp_request_new(OnHttpReqDone, pHttpObj);
	if (req == NULL) {
		fprintf(stderr, "evhttp_request_new() failed\n");
		return false;
	}

	struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_headers, "Host", host);
	evhttp_add_header(output_headers, "Connection", "close");
	evhttp_add_header(output_headers, "Content-Type", "text/plain;text/html;application/x-www-form-urlencoded;charset=utf-8");
	evhttp_add_header(output_headers, "User-Agent", m_strUserAgent.c_str());
	evhttp_add_header(output_headers, "Cache-Control", "no-cache");

	size_t nLen = strPostData.length();
	if (nLen>0)
	{
		struct evbuffer *output_buffer = evhttp_request_get_output_buffer(req);
		evbuffer_add(output_buffer, strPostData.c_str(), nLen);
		char buf[256] = { 0 };
		evutil_snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long)nLen);
		evhttp_add_header(output_headers, "Content-Length", buf);
	}

	int r_ = evhttp_make_request(evcon, req, EVHTTP_REQ_GET, uri);
	if (r_ != 0) {
		fprintf(stderr, "evhttp_make_request() failed\n");
		return false;
	}

	if (http_uri)
	{
		evhttp_uri_free(http_uri);
	}

	return true;
}

bool NFCHttpClient::PerformGet(const std::string& strUri, const std::string& strUserData, HTTP_RESP_FUNCTOR_PTR pCB)
{
	return MakeRequest(strUri, strUserData, "", pCB, false);
}

bool NFCHttpClient::PerformPost(const std::string& strUri, const std::string& strUserData, const std::string& strPostData, HTTP_RESP_FUNCTOR_PTR pCB)
{
	return MakeRequest(strUri, strUserData, strPostData, pCB, true);
}

void NFCHttpClient::OnHttpReqDone(struct evhttp_request *req, void *ctx)
{
	HttpObject* pHttpObj = (HttpObject*)(ctx);

	if (req == NULL) {
		/* If req is NULL, it means an error occurred, but
		* sadly we are mostly left guessing what the error
		* might have been.  We'll do our best... */
		struct bufferevent *bev = (struct bufferevent *) ctx;
		unsigned long oslerr;
		int printed_err = 0;
		int errcode = EVUTIL_SOCKET_ERROR();

		std::string strErrMsg = "";
		fprintf(stderr, "some request failed - no idea which one though!\n");
		/* Print out the OpenSSL error queue that libevent
		* squirreled away for us, if any. */

		char buffer[512] = { 0 };
		int nread = 0;

#if NF_ENABLE_SSL
		while ((oslerr = bufferevent_get_openssl_error(bev))) {
			ERR_error_string_n(oslerr, buffer, sizeof(buffer));
			fprintf(stderr, "%s\n", buffer);
			strErrMsg += std::string(buffer);
			printed_err = 1;
		}
#endif
		/* If the OpenSSL error queue was empty, maybe it was a
		* socket error; let's try printing that. */
		if (!printed_err) {
			char tmpBuf[512] = { 0 };
			snprintf(tmpBuf, 512, "socket error = %s (%d)\n",
				evutil_socket_error_to_string(errcode),
				errcode);
			strErrMsg += std::string(tmpBuf);
		}

		if (pHttpObj->m_pCB)
		{
			if (pHttpObj->m_pCB.get())
			{
				HTTP_RESP_FUNCTOR fun(*pHttpObj->m_pCB.get());
				fun(-1, strErrMsg, pHttpObj->m_strUserData);
			}
		}
		return;
	}

	int nRespCode = evhttp_request_get_response_code(req);
	std::string strRespCodeLine = evhttp_request_get_response_code_line(req);

	char buffer[512] = { 0 };
	int nread = 0;

	std::string strResp;
	while ((nread = evbuffer_remove(evhttp_request_get_input_buffer(req),
		buffer, sizeof(buffer)))
		   > 0) {
		//TODO it's not good idea,to append or memcpy
		strResp += std::string(buffer, nread);
	}

	if (req->evcon)
	{
		evhttp_connection_free(req->evcon);
	}

	if (req->output_headers)
	{
		evhttp_clear_headers(req->output_headers);
	}

	if (pHttpObj)
	{
		if (pHttpObj->m_pBev)
		{
#if NF_ENABLE_SSL
			SSL* pSSL = bufferevent_openssl_get_ssl(pHttpObj->m_pBev);
			SSL_free(pSSL);
#endif
		}
	}

	if (pHttpObj->m_pCB)
	{
		if (pHttpObj->m_pCB.get())
		{
			HTTP_RESP_FUNCTOR fun(*pHttpObj->m_pCB.get());
			fun(nRespCode, strResp, pHttpObj->m_strUserData);
		}
	}
}
<commit_msg>remove unused code<commit_after>////////////////////////////////////////////
//  Filename NFCHttpClient.cpp
//  Copyright (C) 2017  Stonexin
//  CreateTime 2017/07/05
//
////////////////////////////////////////////
#include "NFCHttpClient.h"

#if NF_PLATFORM == NF_PLATFORM_WIN
#include <WS2tcpip.h>
#include <winsock2.h>
#pragma  comment(lib,"Ws2_32.lib")
#pragma  comment(lib,"libevent.lib")
#pragma  comment(lib,"libevent_core.lib")

#if NF_ENABLE_SSL
#pragma  comment(lib,"libevent_openssl.lib")
#pragma  comment(lib,"libeay32.lib")
#pragma  comment(lib,"ssleay32.lib")
#endif

#endif

bool NFCHttpClient::Execute()
{
	if (m_pBase)
	{
		event_base_loop(m_pBase, EVLOOP_ONCE | EVLOOP_NONBLOCK);
	}

	return true;
}

bool NFCHttpClient::Init()
{
#if NF_PLATFORM == NF_PLATFORM_WIN
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(2, 2);
	int err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		return false;
	}
#endif
	m_strUserAgent = DEFAULT_USER_AGENT;// strUserAgent;

#if NF_ENABLE_SSL

#if OPENSSL_VERSION_NUMBER < 0x10100000L
	// Initialize OpenSSL
	SSL_library_init();
	ERR_load_crypto_strings();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
#endif

	m_pSslCtx = SSL_CTX_new(SSLv23_client_method());
	if (!m_pSslCtx) {
		printf("SSL_CTX_new err.");
		return false;
	}

#endif

	m_pBase = event_base_new();
	if (m_pBase == nullptr)
	{
		printf("event_base_new err.");
		return false;
	}
	return true;
}

bool NFCHttpClient::Final()
{
	if (m_pBase)
	{
		event_base_free(m_pBase);
		m_pBase = nullptr;
	}

#if NF_ENABLE_SSL
	if (m_pSslCtx)
	{
		SSL_CTX_free(m_pSslCtx);
		m_pSslCtx = nullptr;
	}

#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
	EVP_cleanup();
	ERR_free_strings();

#if OPENSSL_VERSION_NUMBER < 0x10000000L
	ERR_remove_state(0);
#else
	ERR_remove_thread_state(NULL);
#endif

	CRYPTO_cleanup_all_ex_data();

	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) */
#endif
	return true;
}

bool NFCHttpClient::MakeRequest(const std::string& strUri,
	const std::string& strUserData,
	const std::string& strPostData,
	HTTP_RESP_FUNCTOR_PTR pCB,
	bool bPost)
{
	struct evhttp_uri *http_uri = NULL;
	const char *scheme, *host, *path, *query;

	http_uri = evhttp_uri_parse(strUri.c_str());
	if (http_uri == NULL) {
		return false;
	}

	bool isHttps = false;

	scheme = evhttp_uri_get_scheme(http_uri);
	std::string lowwerScheme(scheme);
	std::transform(lowwerScheme.begin(), lowwerScheme.end(), lowwerScheme.begin(), (int(*)(int))std::tolower);
	if (scheme == NULL || (lowwerScheme.compare("https") != 0 && lowwerScheme.compare("http") != 0)) {
		return false;
	}

	if (lowwerScheme.compare("https") == 0)
	{
		isHttps = true;
	}

	host = evhttp_uri_get_host(http_uri);
	if (host == NULL) {
		printf("url must have a host \n");
		return false;
	}

	int port = evhttp_uri_get_port(http_uri);
	if (port == -1) {
		port = isHttps ? 443 : 80;
	}

	path = evhttp_uri_get_path(http_uri);
	if (strlen(path) == 0) {
		path = "/";
	}

	char uri[512] = { 0 };

	query = evhttp_uri_get_query(http_uri);
	if (query == NULL) {
		snprintf(uri, sizeof(uri) - 1, "%s", path);
	}
	else {
		snprintf(uri, sizeof(uri) - 1, "%s?%s", path, query);
	}
	uri[sizeof(uri) - 1] = '\0';

	//-------we do not verify peer--------//
	//like the curl SSL_VERIFYPEER is set false

	//if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
	//	err_openssl("SSL_CTX_load_verify_locations");
	//	goto error;
	//}
	//SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
	//SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback,(void *)host);

	struct bufferevent* bev = NULL;

#if NF_ENABLE_SSL
	SSL *pSSL = SSL_new(m_pSslCtx);
	if (pSSL == NULL) {
		printf("SSL_new err.");
		return false;
	}
#endif

	if (!isHttps) {
		bev = bufferevent_socket_new(m_pBase, -1, BEV_OPT_CLOSE_ON_FREE);
	}
	else {
#if NF_ENABLE_SSL
		bev = bufferevent_openssl_socket_new(m_pBase, -1, pSSL,
			BUFFEREVENT_SSL_CONNECTING,
			BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
#endif
	}

	if (bev == NULL) {
		fprintf(stderr, "bufferevent_socket_new() failed\n");
		return false;
	}

#if NF_ENABLE_SSL
	if (isHttps)
	{
		bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
	}
#endif

	struct evhttp_connection* evcon = evhttp_connection_base_bufferevent_new(m_pBase, NULL, bev, host, port);
	if (evcon == NULL) {
		fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
		return false;
	}

	if (m_nRetry > 0) {
		evhttp_connection_set_retries(evcon, m_nRetry);
	}
	if (m_nTimeOut >= 0) {
		evhttp_connection_set_timeout(evcon, m_nTimeOut);
	}

	HttpObject* pHttpObj = new HttpObject(this, bev, strUserData, pCB);
	pHttpObj->SetUri(strUri);

	// Fire off the request
	struct evhttp_request* req = evhttp_request_new(OnHttpReqDone, pHttpObj);
	if (req == NULL) {
		fprintf(stderr, "evhttp_request_new() failed\n");
		return false;
	}

	struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_headers, "Host", host);
	evhttp_add_header(output_headers, "Connection", "close");
	evhttp_add_header(output_headers, "Content-Type", "text/plain;text/html;application/x-www-form-urlencoded;charset=utf-8");
	evhttp_add_header(output_headers, "User-Agent", m_strUserAgent.c_str());
	evhttp_add_header(output_headers, "Cache-Control", "no-cache");

	size_t nLen = strPostData.length();
	if (nLen>0)
	{
		struct evbuffer *output_buffer = evhttp_request_get_output_buffer(req);
		evbuffer_add(output_buffer, strPostData.c_str(), nLen);
		char buf[256] = { 0 };
		evutil_snprintf(buf, sizeof(buf) - 1, "%lu", (unsigned long)nLen);
		evhttp_add_header(output_headers, "Content-Length", buf);
	}

	int r_ = evhttp_make_request(evcon, req, EVHTTP_REQ_GET, uri);
	if (r_ != 0) {
		fprintf(stderr, "evhttp_make_request() failed\n");
		return false;
	}

	if (http_uri)
	{
		evhttp_uri_free(http_uri);
	}

	return true;
}

bool NFCHttpClient::PerformGet(const std::string& strUri, const std::string& strUserData, HTTP_RESP_FUNCTOR_PTR pCB)
{
	return MakeRequest(strUri, strUserData, "", pCB, false);
}

bool NFCHttpClient::PerformPost(const std::string& strUri, const std::string& strUserData, const std::string& strPostData, HTTP_RESP_FUNCTOR_PTR pCB)
{
	return MakeRequest(strUri, strUserData, strPostData, pCB, true);
}

void NFCHttpClient::OnHttpReqDone(struct evhttp_request *req, void *ctx)
{
	HttpObject* pHttpObj = (HttpObject*)(ctx);

	if (req == NULL) {
		/* If req is NULL, it means an error occurred, but
		* sadly we are mostly left guessing what the error
		* might have been.  We'll do our best... */
		struct bufferevent *bev = (struct bufferevent *) ctx;
		unsigned long oslerr;
		int printed_err = 0;
		int errcode = EVUTIL_SOCKET_ERROR();

		std::string strErrMsg = "";
		fprintf(stderr, "some request failed - no idea which one though!\n");
		/* Print out the OpenSSL error queue that libevent
		* squirreled away for us, if any. */

		char buffer[512] = { 0 };
		int nread = 0;

#if NF_ENABLE_SSL
		while ((oslerr = bufferevent_get_openssl_error(bev))) {
			ERR_error_string_n(oslerr, buffer, sizeof(buffer));
			fprintf(stderr, "%s\n", buffer);
			strErrMsg += std::string(buffer);
			printed_err = 1;
		}
#endif
		/* If the OpenSSL error queue was empty, maybe it was a
		* socket error; let's try printing that. */
		if (!printed_err) {
			char tmpBuf[512] = { 0 };
			snprintf(tmpBuf, 512, "socket error = %s (%d)\n",
				evutil_socket_error_to_string(errcode),
				errcode);
			strErrMsg += std::string(tmpBuf);
		}

		if (pHttpObj->m_pCB)
		{
			if (pHttpObj->m_pCB.get())
			{
				HTTP_RESP_FUNCTOR fun(*pHttpObj->m_pCB.get());
				fun(-1, strErrMsg, pHttpObj->m_strUserData);
			}
		}
		return;
	}

	int nRespCode = evhttp_request_get_response_code(req);
	char buffer[512] = { 0 };
	int nread = 0;
	std::string strResp;
	while ((nread = evbuffer_remove(evhttp_request_get_input_buffer(req),
		buffer, sizeof(buffer)))
		   > 0) {
		//TODO it's not good idea,to append or memcpy
		strResp += std::string(buffer, nread);
	}

	if (req->evcon)
	{
		evhttp_connection_free(req->evcon);
	}

	if (req->output_headers)
	{
		evhttp_clear_headers(req->output_headers);
	}

	if (pHttpObj)
	{
		if (pHttpObj->m_pBev)
		{
#if NF_ENABLE_SSL
			SSL* pSSL = bufferevent_openssl_get_ssl(pHttpObj->m_pBev);
			SSL_free(pSSL);
#endif
		}
	}

	if (pHttpObj->m_pCB)
	{
		if (pHttpObj->m_pCB.get())
		{
			HTTP_RESP_FUNCTOR fun(*pHttpObj->m_pCB.get());
			fun(nRespCode, strResp, pHttpObj->m_strUserData);
		}
	}
}
<|endoftext|>


<commit_before>// $Id $
//
// Tests that each form of 4-vector has all the properties that stem from
// owning and forwarding to a 4D coordinates instance
//
// 6/28/05 m fischler
//         from contents of test_coordinates.h by L. Moneta.
//
// =================================================================

#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/Cartesian3D.h"
#include "Math/GenVector/Polar3D.h"
#include "Math/GenVector/CylindricalEta3D.h"
#include "Math/GenVector/etaMax.h"

#include "Math/GenVector/PxPyPzE4D.h"
#include "Math/GenVector/PxPyPzM4D.h"
#include "Math/GenVector/PtEtaPhiE4D.h"
#include "Math/GenVector/PtEtaPhiM4D.h"
#include "Math/GenVector/LorentzVector.h"

#include "Math/Vector4Dfwd.h"  // for typedefs definitions

#include "CoordinateTraits.h"

#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

//#define TRACE1
#define DEBUG

using namespace ROOT::Math;

template <typename T1, typename T2 >
struct Precision {
  enum { result = std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits   };
};

template <typename T1, typename T2, bool>
struct LessPreciseType {
  typedef T1 type;
};
template <typename T1, typename T2>
struct LessPreciseType<T1, T2, false> {
  typedef T2 type;
};

template <typename Scalar1, typename Scalar2>
int
closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) {
  int ret = 0;
  Scalar1 eps1 = std::numeric_limits<Scalar1>::epsilon();
  Scalar2 eps2 = std::numeric_limits<Scalar2>::epsilon();
  typedef typename LessPreciseType<Scalar1, Scalar2,Precision<Scalar1,Scalar2>::result>::type Scalar;
  Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2;
  int pr = std::cout.precision(18);
  Scalar ss1 (s1);
  Scalar ss2 (s2);
  Scalar diff = ss1 - ss2;
  if (diff < 0) diff = -diff;
  if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change??
    if ( diff > ticks*epsilon ) {
      ret=3;
      std::cout << "\nAbsolute discrepancy in " << coord << "(): "
                << ss1 << " != " << ss2 << "\n"
                << "   (Allowed discrepancy is " << ticks*epsilon
                << ")\nDifference is " << diff/epsilon << " ticks\n";
    }
    std::cout.precision (pr);
    return ret;
  }
  // infinity dicrepancy musy be checked with max precision
  long double sd1(ss1);
  long double sd2(ss2);
  if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) {
    ret=5;
    std::cout << "\nInfinity discrepancy in " << coord << "(): "
              << sd1 << " != " << sd2 << "\n";
    std::cout.precision (pr);
    return ret;
  }
  Scalar denom = ss1 > 0 ? ss1 : -ss1;
  if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) {
    ret=9;
    std::cout << "\nDiscrepancy in " << coord << "(): "
              << ss1 << " != " << ss2 << "\n"
              << "   (Allowed discrepancy is " << ticks*epsilon*ss1
              << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n";
  }
  std::cout.precision (pr);
  return ret;
}

template <class V1, class V2>
int compare4D (const V1 & v1, const V2 & v2, double ticks) {
  int ret =0;
  typedef typename V1::CoordinateType CoordType1;
  typedef typename V2::CoordinateType CoordType2;

  ret |= closeEnough ( v1.x(),     v2.x(),     "x"     ,ticks);
  ret |= closeEnough ( v1.y(),     v2.y(),     "y"     ,ticks);
  ret |= closeEnough ( v1.z(),     v2.z(),     "z"     ,ticks);
  ret |= closeEnough ( v1.t(),     v2.t(),     "t"     ,ticks);
  ret |= closeEnough ( v1.rho(),   v2.rho(),   "rho"   ,ticks);
  ret |= closeEnough ( v1.phi(),   v2.phi(),   "phi"   ,ticks);
  ret |= closeEnough ( v1.P(),     v2.P(),     "p"     ,ticks);
  ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks);
  ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks);
  ret |= closeEnough ( v1.M2(),    v2.M2(),    "m2"    ,ticks);
  ret |= closeEnough ( v1.M(),     v2.M(),     "m"     ,ticks);
  ret |= closeEnough ( v1.Mt(),    v2.Mt(),    "mt"     ,ticks);
  ret |= closeEnough ( v1.Et(),    v2.Et(),    "et"     ,ticks);
  if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0
    ret |= closeEnough ( v1.eta(), v2.eta(),   "eta"   ,ticks);
  }

  if (ret != 0) {
    std::cout << "Discrepancy detected (see above) is between:\n  "
              << CoordinateTraits<CoordType1>::name() << " and\n  "
              << CoordinateTraits<CoordType2>::name() << "\n"
              << "with v = (" << v1.x() << ", " << v1.y() << ", "
              << v1.z() << ", " << v1.t() << ")\n";
  }
  else {
    std::cout << ".";
  }

  return ret;
}

template <class C>
int test4D ( const LorentzVector<C> & v, double ticks ) {

#ifdef DEBUG
   std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: ";
#endif

  int ret = 0;
  LorentzVector< PxPyPzE4D<double> > vxyzt_d (v.x(), v.y(), v.z(), v.t());

  //double m = std::sqrt ( v.t()*v.t() - v.x()*v.x() - v.y()*v.y() - v.z()*v.z());
  //double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z());
  double rho = std::sqrt (v.x()*v.x() + v.y()*v.y());
  double theta = std::atan2( rho, v.z() );  // better tahn using acos
  //double theta = r>0 ? std::acos ( v.z()/r ) : 0;
  double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0;

  double eta;
  if (rho != 0) {
    eta = -std::log(std::tan(theta/2));
   #ifdef TRACE1
   std::cout <<  ":::: rho != 0\n"
             <<  ":::: theta = " <<  theta
        <<"/n:::: tan(theta/2) = " << std::tan(theta/2)
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else if (v.z() == 0) {
    eta = 0;
   #ifdef TRACE1
   std::cout <<  ":::: v.z() == 0\n"
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else if (v.z() > 0) {
    eta = v.z() + etaMax<long double>();
   #ifdef TRACE1
   std::cout <<  ":::: v.z() > 0\n"
             <<  ":::: etaMax =  " << etaMax<long double>()
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else {
    eta = v.z() - etaMax<long double>();
   #ifdef TRACE1
   std::cout <<  ":::: v.z() < 0\n"
             <<  ":::: etaMax =  " << etaMax<long double>()
             <<"\n:::: eta = " << eta << "\n";
   #endif
  }

  LorentzVector< PtEtaPhiE4D<double> > vrep_d ( rho, eta, phi, v.t() );
  ret |= compare4D( vxyzt_d, vrep_d, ticks);

  LorentzVector< PtEtaPhiM4D<double> > vrepm_d ( rho, eta, phi, v.M() );
  ret |= compare4D( vxyzt_d, vrepm_d, ticks);

  LorentzVector< PxPyPzM4D  <double> > vxyzm_d ( v.x(), v.y(), v.z(), v.M() );
  ret |= compare4D( vrep_d, vxyzm_d, ticks);

  LorentzVector< PxPyPzE4D<float> >      vxyzt_f (v.x(), v.y(), v.z(), v.t());
  ret |= compare4D( vxyzt_d, vxyzt_f, ticks);

  LorentzVector< PtEtaPhiE4D<float> > vrep_f ( rho, eta, phi, v.t() );
  ret |= compare4D( vxyzt_f, vrep_f, ticks);

  LorentzVector< PtEtaPhiM4D<float> > vrepm_f ( rho, eta, phi, v.M() );
  ret |= compare4D( vxyzt_f, vrepm_f, ticks);

  LorentzVector< PxPyPzM4D<float> >      vxyzm_f (v.x(), v.y(), v.z(), v.M());
  ret |= compare4D( vrep_f, vxyzm_f, ticks);

  if (ret == 0) std::cout << "\t OK\n";
  else {
     std::cout << "\t FAIL\n";
     std::cerr << "\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks
               << "\t:\t FAILED\n";
  }
  return ret;
}

int coordinates4D (bool testAll = false) {
  int ret = 0;

  ret |= test4D (XYZTVector ( 0.0, 0.0, 0.0, 0.0 )     , 1 );
  ret |= test4D (XYZTVector ( 1.0, 2.0, 3.0, 4.0 )     ,10 );
  ret |= test4D (XYZTVector ( -1.0, -2.0, 3.0, 4.0 )   ,10 );
  // test for large eta values (which was giving inf before  Jun 07)
  ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, 10.0, 100.0 )   ,10 );
  // for z < 0 precision in eta is worse since theta is close to Pi
  ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, -10.0, 100.0 )   ,1000000000 );

  // test cases with zero mass

  // tick should be p /sqrt(eps) ~ 4 /sqrt(eps)
  ret |= test4D (PxPyPzMVector ( 1., 2., 3., 0.)  ,  4./std::sqrt(std::numeric_limits<double>::epsilon()) );

  // this test fails in some machines (skip by default)
  if (!testAll) return ret;

  // take a factor 1.5 in ticks to be conservative
  ret |= test4D (PxPyPzMVector ( 1., 1., 100., 0.)  ,  150./std::sqrt(std::numeric_limits<double>::epsilon()) );
  // need a larger  a factor here
  ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.)  ,  1.E9/std::sqrt(std::numeric_limits<double>::epsilon()) );
  // if use 1 here fails
  ret |= test4D (PxPyPzMVector ( 1.E-8, 1.E-8, 1.E-8, 0.)  ,  2.E-8/std::sqrt(std::numeric_limits<double>::epsilon()) );

  return ret;
}

int main() {
   int ret = coordinates4D();
   if (ret)  std::cerr << "test FAILED !!! " << std::endl;
   else   std::cout << "test OK " << std::endl;
   return ret;
}
<commit_msg>Attempt to fix roottest_root_math_genvector_coordinates4D on  ARM64.<commit_after>// $Id $
//
// Tests that each form of 4-vector has all the properties that stem from
// owning and forwarding to a 4D coordinates instance
//
// 6/28/05 m fischler
//         from contents of test_coordinates.h by L. Moneta.
//
// =================================================================

#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/Cartesian3D.h"
#include "Math/GenVector/Polar3D.h"
#include "Math/GenVector/CylindricalEta3D.h"
#include "Math/GenVector/etaMax.h"

#include "Math/GenVector/PxPyPzE4D.h"
#include "Math/GenVector/PxPyPzM4D.h"
#include "Math/GenVector/PtEtaPhiE4D.h"
#include "Math/GenVector/PtEtaPhiM4D.h"
#include "Math/GenVector/LorentzVector.h"

#include "Math/Vector4Dfwd.h"  // for typedefs definitions

#include "CoordinateTraits.h"

#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

//#define TRACE1
#define DEBUG

using namespace ROOT::Math;

template <typename T1, typename T2 >
struct Precision {
  enum { result = std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits   };
};

template <typename T1, typename T2, bool>
struct LessPreciseType {
  typedef T1 type;
};
template <typename T1, typename T2>
struct LessPreciseType<T1, T2, false> {
  typedef T2 type;
};

template <typename Scalar1, typename Scalar2>
int
closeEnough ( Scalar1 s1, Scalar2 s2, std::string const & coord, double ticks ) {
  int ret = 0;
  Scalar1 eps1 = std::numeric_limits<Scalar1>::epsilon();
  Scalar2 eps2 = std::numeric_limits<Scalar2>::epsilon();
  typedef typename LessPreciseType<Scalar1, Scalar2,Precision<Scalar1,Scalar2>::result>::type Scalar;
  Scalar epsilon = (eps1 >= eps2) ? eps1 : eps2;
  int pr = std::cout.precision(18);
  Scalar ss1 (s1);
  Scalar ss2 (s2);
  Scalar diff = ss1 - ss2;
  if (diff < 0) diff = -diff;
  if (ss1 == 0 || ss2 == 0) { // TODO - the ss2==0 makes a big change??
    if ( diff > ticks*epsilon ) {
      ret=3;
      std::cout << "\nAbsolute discrepancy in " << coord << "(): "
                << ss1 << " != " << ss2 << "\n"
                << "   (Allowed discrepancy is " << ticks*epsilon
                << ")\nDifference is " << diff/epsilon << " ticks\n";
    }
    std::cout.precision (pr);
    return ret;
  }
  // infinity dicrepancy musy be checked with max precision
  long double sd1(ss1);
  long double sd2(ss2);
  if ( (sd1 + sd2 == sd1) != (sd1 + sd2 == sd2) ) {
    ret=5;
    std::cout << "\nInfinity discrepancy in " << coord << "(): "
              << sd1 << " != " << sd2 << "\n";
    std::cout.precision (pr);
    return ret;
  }
  Scalar denom = ss1 > 0 ? ss1 : -ss1;
  if ((diff/denom > ticks*epsilon) && (diff > ticks*epsilon)) {
    ret=9;
    std::cout << "\nDiscrepancy in " << coord << "(): "
              << ss1 << " != " << ss2 << "\n"
              << "   (Allowed discrepancy is " << ticks*epsilon*ss1
              << ")\nDifference is " << (diff/denom)/epsilon << " ticks\n";
  }
  std::cout.precision (pr);
  return ret;
}

template <class V1, class V2>
int compare4D (const V1 & v1, const V2 & v2, double ticks) {
  int ret =0;
  typedef typename V1::CoordinateType CoordType1;
  typedef typename V2::CoordinateType CoordType2;

  ret |= closeEnough ( v1.x(),     v2.x(),     "x"     ,ticks);
  ret |= closeEnough ( v1.y(),     v2.y(),     "y"     ,ticks);
  ret |= closeEnough ( v1.z(),     v2.z(),     "z"     ,ticks);
  ret |= closeEnough ( v1.t(),     v2.t(),     "t"     ,ticks);
  ret |= closeEnough ( v1.rho(),   v2.rho(),   "rho"   ,ticks);
  ret |= closeEnough ( v1.phi(),   v2.phi(),   "phi"   ,ticks);
  ret |= closeEnough ( v1.P(),     v2.P(),     "p"     ,ticks);
  ret |= closeEnough ( v1.theta(), v2.theta(), "theta" ,ticks);
  ret |= closeEnough ( v1.perp2(), v2.perp2(), "perp2" ,ticks);
  ret |= closeEnough ( v1.M2(),    v2.M2(),    "m2"    ,ticks);
  ret |= closeEnough ( v1.M(),     v2.M(),     "m"     ,ticks);
  ret |= closeEnough ( v1.Mt(),    v2.Mt(),    "mt"     ,ticks);
  ret |= closeEnough ( v1.Et(),    v2.Et(),    "et"     ,ticks);
  if ( v1.rho() > 0 && v2.rho() > 0 ) { // eta can legitimately vary if rho == 0
    ret |= closeEnough ( v1.eta(), v2.eta(),   "eta"   ,ticks);
  }

  if (ret != 0) {
    std::cout << "Discrepancy detected (see above) is between:\n  "
              << CoordinateTraits<CoordType1>::name() << " and\n  "
              << CoordinateTraits<CoordType2>::name() << "\n"
              << "with v = (" << v1.x() << ", " << v1.y() << ", "
              << v1.z() << ", " << v1.t() << ")\n";
  }
  else {
    std::cout << ".";
  }

  return ret;
}

template <class C>
int test4D ( const LorentzVector<C> & v, double ticks ) {

#ifdef DEBUG
   std::cout <<"\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks << "\t: ";
#endif

  int ret = 0;
  LorentzVector< PxPyPzE4D<double> > vxyzt_d (v.x(), v.y(), v.z(), v.t());

  //double m = std::sqrt ( v.t()*v.t() - v.x()*v.x() - v.y()*v.y() - v.z()*v.z());
  //double r = std::sqrt (v.x()*v.x() + v.y()*v.y() + v.z()*v.z());
  double rho = std::sqrt (v.x()*v.x() + v.y()*v.y());
  double theta = std::atan2( rho, v.z() );  // better tahn using acos
  //double theta = r>0 ? std::acos ( v.z()/r ) : 0;
  double phi = rho>0 ? std::atan2 (v.y(), v.x()) : 0;

  double eta;
  if (rho != 0) {
    eta = -std::log(std::tan(theta/2));
   #ifdef TRACE1
   std::cout <<  ":::: rho != 0\n"
             <<  ":::: theta = " <<  theta
        <<"/n:::: tan(theta/2) = " << std::tan(theta/2)
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else if (v.z() == 0) {
    eta = 0;
   #ifdef TRACE1
   std::cout <<  ":::: v.z() == 0\n"
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else if (v.z() > 0) {
    eta = v.z() + etaMax<long double>();
   #ifdef TRACE1
   std::cout <<  ":::: v.z() > 0\n"
             <<  ":::: etaMax =  " << etaMax<long double>()
             <<"\n:::: eta = " << eta << "\n";
   #endif
  } else {
    eta = v.z() - etaMax<long double>();
   #ifdef TRACE1
   std::cout <<  ":::: v.z() < 0\n"
             <<  ":::: etaMax =  " << etaMax<long double>()
             <<"\n:::: eta = " << eta << "\n";
   #endif
  }

  LorentzVector< PtEtaPhiE4D<double> > vrep_d ( rho, eta, phi, v.t() );
  ret |= compare4D( vxyzt_d, vrep_d, ticks);

  LorentzVector< PtEtaPhiM4D<double> > vrepm_d ( rho, eta, phi, v.M() );
  ret |= compare4D( vxyzt_d, vrepm_d, ticks);

  LorentzVector< PxPyPzM4D  <double> > vxyzm_d ( v.x(), v.y(), v.z(), v.M() );
  ret |= compare4D( vrep_d, vxyzm_d, ticks);

  LorentzVector< PxPyPzE4D<float> >      vxyzt_f (v.x(), v.y(), v.z(), v.t());
  ret |= compare4D( vxyzt_d, vxyzt_f, ticks);

  LorentzVector< PtEtaPhiE4D<float> > vrep_f ( rho, eta, phi, v.t() );
  ret |= compare4D( vxyzt_f, vrep_f, ticks);

  LorentzVector< PtEtaPhiM4D<float> > vrepm_f ( rho, eta, phi, v.M() );
  ret |= compare4D( vxyzt_f, vrepm_f, ticks);

  LorentzVector< PxPyPzM4D<float> >      vxyzm_f (v.x(), v.y(), v.z(), v.M());
  ret |= compare4D( vrep_f, vxyzm_f, ticks);

  if (ret == 0) std::cout << "\t OK\n";
  else {
     std::cout << "\t FAIL\n";
     std::cerr << "\n>>>>> Testing LorentzVector from " << XYZTVector(v) << " ticks = " << ticks
               << "\t:\t FAILED\n";
  }
  return ret;
}

int coordinates4D (bool testAll = false) {
  int ret = 0;

  ret |= test4D (XYZTVector ( 0.0, 0.0, 0.0, 0.0 )     , 1 );
  ret |= test4D (XYZTVector ( 1.0, 2.0, 3.0, 4.0 )     ,10 );
  ret |= test4D (XYZTVector ( -1.0, -2.0, 3.0, 4.0 )   ,10 );
  // test for large eta values (which was giving inf before  Jun 07)
  ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, 10.0, 100.0 )   ,10 );
  // for z < 0 precision in eta is worse since theta is close to Pi
  ret |= test4D (XYZTVector ( 1.E-8, 1.E-8, -10.0, 100.0 )   ,1000000000 );

  // test cases with zero mass

  // tick should be p /sqrt(eps) ~ 4 /sqrt(eps)
  // take a factor 1.5 in ticks to be conservative
  ret |= test4D (PxPyPzMVector ( 1., 2., 3., 0.)  ,  1.5 * 4./std::sqrt(std::numeric_limits<double>::epsilon()) );

  // this test fails in some machines (skip by default)
  if (!testAll) return ret;

  // take a factor 1.5 in ticks to be conservative
  ret |= test4D (PxPyPzMVector ( 1., 1., 100., 0.)  ,  150./std::sqrt(std::numeric_limits<double>::epsilon()) );
  // need a larger  a factor here
  ret |= test4D (PxPyPzMVector ( 1.E8, 1.E8, 1.E8, 0.)  ,  1.E9/std::sqrt(std::numeric_limits<double>::epsilon()) );
  // if use 1 here fails
  ret |= test4D (PxPyPzMVector ( 1.E-8, 1.E-8, 1.E-8, 0.)  ,  2.E-8/std::sqrt(std::numeric_limits<double>::epsilon()) );

  return ret;
}

int main() {
   int ret = coordinates4D();
   if (ret)  std::cerr << "test FAILED !!! " << std::endl;
   else   std::cout << "test OK " << std::endl;
   return ret;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef KERNEL_HPP_
#define KERNEL_HPP_

#include "top.hpp"
#include "platform/object.hpp"

#include "amdocl/cl_kernel.h"

#include <vector>
#include <cstdlib>  // for malloc
#include <string>
#include "device/device.hpp"

enum FGSStatus {
  FGS_DEFAULT,  //!< The default kernel fine-grained system pointer support
  FGS_NO,       //!< no support of kernel fine-grained system pointer
  FGS_YES       //!< have support of kernel fine-grained system pointer
};

namespace amd {

class Symbol;
class Program;

/*! \addtogroup Runtime
 *  @{
 *
 *  \addtogroup Program Programs and Kernel functions
 *  @{
 */

class KernelSignature : public HeapObject {
 private:
  std::vector<KernelParameterDescriptor> params_;
  std::vector<KernelParameterDescriptor> hiddenParams_;
  std::string attributes_;  //!< The kernel attributes
  uint32_t  paramsSize_;
  uint32_t  numMemories_;
  uint32_t  numSamplers_;
  uint32_t  numQueues_;
  uint32_t  version_;

 public:
  enum {
    ABIVersion_0 = 0,   //! ABI constructed based on the OCL semantics
    ABIVersion_1 = 1    //! ABI constructed based on the HW ABI returned from the compiler
  };

  //! Default constructor
  KernelSignature():
    paramsSize_(0), numMemories_(0), numSamplers_(0),
    numQueues_(0), version_(ABIVersion_0) {}

  //! Construct a new signature.
  KernelSignature(const std::vector<KernelParameterDescriptor>& params,
    const std::string& attrib,
    const std::vector<KernelParameterDescriptor>& hiddenParams,
    uint32_t version);

  //! Return the number of parameters
  size_t numParameters() const { return params_.size(); }

  //! Return the parameter descriptor at the given index.
  const KernelParameterDescriptor& at(size_t index) const {
    assert(index < params_.size() && "index is out of bounds");
    return params_[index];
  }

  std::vector<KernelParameterDescriptor>& params() { return params_; }

  //! Return the size in bytes required for the arguments on the stack.
  uint32_t paramsSize() const { return paramsSize_; }

  //! Returns the number of memory objects.
  uint32_t numMemories() const { return numMemories_; }

  //! Returns the number of sampler objects.
  uint32_t numSamplers() const { return numSamplers_; }

  //! Returns the number of queue objects.
  uint32_t numQueues() const { return numQueues_; }

  //! Returns the signature version
  uint32_t version() const { return version_; }

  //! Return the kernel attributes
  const std::string& attributes() const { return attributes_; }

  const std::vector<KernelParameterDescriptor>& hiddenParameters() const
    { return hiddenParams_; }

  const std::vector<KernelParameterDescriptor>& parameters() const
    { return params_; }
};

// @todo: look into a copy-on-write model instead of copy-on-read.
//
class KernelParameters : protected HeapObject {
 private:
  //! The signature describing these parameters.
  KernelSignature& signature_;

  address values_;                      //!< pointer to the base of the values stack.
  uint32_t execInfoOffset_;             //!< The offset of execInfo
  std::vector<void*> execSvmPtr_;       //!< The non argument svm pointers for kernel
  FGSStatus svmSystemPointersSupport_;  //!< The flag for the status of the kernel
                                        //   support of fine-grain system sharing.
  uint32_t  memoryObjOffset_;       //!< The offset of execInfo
  uint32_t  samplerObjOffset_;      //!< The offset of execInfo
  uint32_t  queueObjOffset_;        //!< The offset of execInfo
  amd::Memory** memoryObjects_;     //!< The non argument svm pointers for kernel
  amd::Sampler** samplerObjects_;   //!< The non argument svm pointers for kernel
  amd::DeviceQueue** queueObjects_; //!< The non argument svm pointers for kernel

  uint32_t  totalSize_;             //!< The total size of all captured parameters

  struct {
    uint32_t validated_ : 1;     //!< True if all parameters are defined.
    uint32_t execNewVcop_ : 1;   //!< special new VCOP for kernel execution
    uint32_t execPfpaVcop_ : 1;  //!< special PFPA VCOP for kernel execution
    uint32_t unused : 29;        //!< unused
  };

 public:
  //! Construct a new instance of parameters for the given signature.
  KernelParameters(KernelSignature& signature)
      : signature_(signature),
        execInfoOffset_(0),
        svmSystemPointersSupport_(FGS_DEFAULT),
        memoryObjects_(nullptr),
        samplerObjects_(nullptr),
        queueObjects_(nullptr),
        validated_(0),
        execNewVcop_(0),
        execPfpaVcop_(0) {
    totalSize_ = signature.paramsSize() + (signature.numMemories() +
        signature.numSamplers() + signature.numQueues()) * sizeof(void*);
    values_ = reinterpret_cast<address>(this) + alignUp(sizeof(KernelParameters), 16);
    memoryObjOffset_ = signature_.paramsSize();
    memoryObjects_ = reinterpret_cast<amd::Memory**>(values_ + memoryObjOffset_);
    samplerObjOffset_ = memoryObjOffset_ + signature_.numMemories() * sizeof(amd::Memory*);
    samplerObjects_ = reinterpret_cast<amd::Sampler**>(values_ + samplerObjOffset_);
    queueObjOffset_ = samplerObjOffset_ + signature_.numSamplers() * sizeof(amd::Sampler*);
    queueObjects_ = reinterpret_cast<amd::DeviceQueue**>(values_ + queueObjOffset_);
    address limit = reinterpret_cast<address>(&queueObjects_[signature_.numQueues()]);
    ::memset(values_, '\0', limit - values_);
  }

  explicit KernelParameters(const KernelParameters& rhs)
      : signature_(rhs.signature_),
        execInfoOffset_(rhs.execInfoOffset_),
        execSvmPtr_(rhs.execSvmPtr_),
        svmSystemPointersSupport_(rhs.svmSystemPointersSupport_),
        memoryObjects_(nullptr),
        samplerObjects_(nullptr),
        queueObjects_(nullptr),
        totalSize_(rhs.totalSize_),
        validated_(rhs.validated_),
        execNewVcop_(rhs.execNewVcop_),
        execPfpaVcop_(rhs.execPfpaVcop_) {
    values_ = reinterpret_cast<address>(this) + alignUp(sizeof(KernelParameters), 16);
    memoryObjOffset_ = signature_.paramsSize();
    memoryObjects_ = reinterpret_cast<amd::Memory**>(values_ + memoryObjOffset_);
    samplerObjOffset_ = memoryObjOffset_ + signature_.numMemories() * sizeof(amd::Memory*);
    samplerObjects_ = reinterpret_cast<amd::Sampler**>(values_ + samplerObjOffset_);
    queueObjOffset_ = samplerObjOffset_ + signature_.numSamplers() * sizeof(amd::Sampler*);
    queueObjects_ = reinterpret_cast<amd::DeviceQueue**>(values_ + queueObjOffset_);
    address limit = reinterpret_cast<address>(&queueObjects_[signature_.numQueues()]);
    ::memcpy(values_, rhs.values_, limit - values_);
  }

  //! Reset the parameter at the given \a index (becomes undefined).
  void reset(size_t index) {
    signature_.params()[index].info_.defined_ = false;
    validated_ = 0;
  }
  //! Set the parameter at the given \a index to the value pointed by \a value
  // \a svmBound indicates that \a value is a SVM pointer.
  void set(size_t index, size_t size, const void* value, bool svmBound = false);

  //! Return true if the parameter at the given \a index is defined.
  bool test(size_t index) const { return signature_.at(index).info_.defined_; }

  //! Return true if all the parameters have been defined.
  bool check();

  //! The amount of memory required for local memory needed
  size_t localMemSize(size_t minDataTypeAlignment) const;

  //! Capture the state of the parameters and return the stack base pointer.
  address capture(const Device& device, cl_int* error);
  //! Release the captured state of the parameters.
  void release(address parameters, const amd::Device& device) const;

  //! Allocate memory for this instance as well as the required storage for
  //  the values_, defined_, and rawPointer_ arrays.
  void* operator new(size_t size, const KernelSignature& signature) {
    size_t requiredSize = alignUp(size, 16) + signature.paramsSize() +
      (signature.numMemories() + signature.numSamplers() + signature.numQueues()) *
       sizeof(void*);
    return AlignedMemory::allocate(requiredSize, PARAMETERS_MIN_ALIGNMENT);
  }
  //! Deallocate the memory reserved for this instance.
  void operator delete(void* ptr) { AlignedMemory::deallocate(ptr); }

  //! Deallocate the memory reserved for this instance,
  // matching overloaded operator new.
  void operator delete(void* ptr, const KernelSignature& signature) {
    AlignedMemory::deallocate(ptr);
  }

  //! Returns raw kernel parameters without capture
  address values() const { return values_; }

  //! Return true if the captured parameter at the given \a index is bound to
  // SVM pointer.
  bool boundToSvmPointer(const Device& device, const_address capturedAddress, size_t index) const;
  //! add the svmPtr execInfo into container
  void addSvmPtr(void* const* execInfoArray, size_t count) {
    execSvmPtr_.clear();
    for (size_t i = 0; i < count; i++) {
      execSvmPtr_.push_back(execInfoArray[i]);
    }
  }
  //! get the number of svmPtr in the execInfo container
  size_t getNumberOfSvmPtr() const { return execSvmPtr_.size(); }

  //! get the offset of svmPtr in the parameters
  uint32_t getExecInfoOffset() const { return execInfoOffset_; }

  //! get the offset of memory objects in the parameters
  uint32_t memoryObjOffset() const { return memoryObjOffset_; }

  //! get the offset of sampler objects in the parameters
  uint32_t samplerObjOffset() const { return samplerObjOffset_; }

  //! get the offset of memory objects in the parameters
  uint32_t queueObjOffset() const { return queueObjOffset_; }

  //! set the status of kernel support fine-grained SVM system pointer sharing
  void setSvmSystemPointersSupport(FGSStatus svmSystemSupport) {
    svmSystemPointersSupport_ = svmSystemSupport;
  }

  //! return the status of kernel support fine-grained SVM system pointer sharing
  FGSStatus getSvmSystemPointersSupport() const { return svmSystemPointersSupport_; }

  //! set the new VCOP in the execInfo container
  void setExecNewVcop(const bool newVcop) { execNewVcop_ = (newVcop == true); }

  //! set the PFPA VCOP in the execInfo container
  void setExecPfpaVcop(const bool pfpaVcop) { execPfpaVcop_ = (pfpaVcop == true); }

  //! get the new VCOP in the execInfo container
  bool getExecNewVcop() const { return (execNewVcop_ == 1); }

  //! get the PFPA VCOP in the execInfo container
  bool getExecPfpaVcop() const { return (execPfpaVcop_ == 1); }
};

/*! \brief Encapsulates a __kernel function and the argument values
 *  to be used when invoking this function.
 */
class Kernel : public RuntimeObject {
 private:
  //! The program where this kernel is defined.
  SharedReference<Program> program_;

  const Symbol& symbol_;          //!< The symbol for this kernel.
  std::string name_;              //!< The kernel's name.
  KernelParameters* parameters_;  //!< The parameters.

 protected:
  //! Destroy this kernel
  ~Kernel();

 public:
  /*! \brief Construct a kernel object from the __kernel function
   *  \a kernelName in the given \a program.
   */
  Kernel(Program& program, const Symbol& symbol, const std::string& name);

  //! Construct a new kernel object from an existing one. Used by CloneKernel.
  explicit Kernel(const Kernel& rhs);

  //! Return the program containing this kernel.
  Program& program() const { return program_(); }

  //! Return this kernel's signature.
  const KernelSignature& signature() const;

  //! Return the kernel entry point for the given device.
  const device::Kernel* getDeviceKernel(const Device& device  //!< Device object
                                        ) const;

  //! Return the parameters.
  KernelParameters& parameters() const { return *parameters_; }

  //! Return the kernel's name.
  const std::string& name() const { return name_; }

  virtual ObjectType objectType() const { return ObjectTypeKernel; }
};

/*! @}
 *  @}
 */

}  // namespace amd

#endif /*KERNEL_HPP_*/
<commit_msg>P4 to Git Change 1567950 by gandryey@gera-w8 on 2018/06/13 17:11:26<commit_after>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef KERNEL_HPP_
#define KERNEL_HPP_

#include "top.hpp"
#include "platform/object.hpp"

#include "amdocl/cl_kernel.h"

#include <vector>
#include <cstdlib>  // for malloc
#include <string>
#include "device/device.hpp"

enum FGSStatus {
  FGS_DEFAULT,  //!< The default kernel fine-grained system pointer support
  FGS_NO,       //!< no support of kernel fine-grained system pointer
  FGS_YES       //!< have support of kernel fine-grained system pointer
};

namespace amd {

class Symbol;
class Program;

/*! \addtogroup Runtime
 *  @{
 *
 *  \addtogroup Program Programs and Kernel functions
 *  @{
 */

class KernelSignature : public HeapObject {
 private:
  std::vector<KernelParameterDescriptor> params_;
  std::string attributes_;  //!< The kernel attributes

  uint32_t  numParameters_; //!< Number of OCL arguments in the kernel
  uint32_t  paramsSize_;    //!< The size of all arguments
  uint32_t  numMemories_;   //!< The number of memory objects used in the kernel
  uint32_t  numSamplers_;   //!< The number of sampler objects used in the kernel
  uint32_t  numQueues_;     //!< The number of queue objects used in the kernel
  uint32_t  version_;       //!< The ABI version

 public:
  enum {
    ABIVersion_0 = 0,   //! ABI constructed based on the OCL semantics
    ABIVersion_1 = 1    //! ABI constructed based on the HW ABI returned from the compiler
  };

  //! Default constructor
  KernelSignature():
    numParameters_(0), paramsSize_(0), numMemories_(0), numSamplers_(0),
    numQueues_(0), version_(ABIVersion_0) {}

  //! Construct a new signature.
  KernelSignature(const std::vector<KernelParameterDescriptor>& params,
    const std::string& attrib,
    uint32_t numParameters,
    uint32_t version);

  //! Return the number of parameters
  uint32_t numParameters() const { return numParameters_; }

  //! Return the total number of parameters, including hidden
  uint32_t numParametersAll() const { return params_.size(); }

  //! Return the parameter descriptor at the given index.
  const KernelParameterDescriptor& at(size_t index) const {
    assert(index < params_.size() && "index is out of bounds");
    return params_[index];
  }

  std::vector<KernelParameterDescriptor>& params() { return params_; }

  //! Return the size in bytes required for the arguments on the stack.
  uint32_t paramsSize() const { return paramsSize_; }

  //! Returns the number of memory objects.
  uint32_t numMemories() const { return numMemories_; }

  //! Returns the number of sampler objects.
  uint32_t numSamplers() const { return numSamplers_; }

  //! Returns the number of queue objects.
  uint32_t numQueues() const { return numQueues_; }

  //! Returns the signature version
  uint32_t version() const { return version_; }

  //! Return the kernel attributes
  const std::string& attributes() const { return attributes_; }

  const std::vector<KernelParameterDescriptor>& parameters() const
    { return params_; }
};

// @todo: look into a copy-on-write model instead of copy-on-read.
//
class KernelParameters : protected HeapObject {
 private:
  //! The signature describing these parameters.
  KernelSignature& signature_;

  address values_;                      //!< pointer to the base of the values stack.
  uint32_t execInfoOffset_;             //!< The offset of execInfo
  std::vector<void*> execSvmPtr_;       //!< The non argument svm pointers for kernel
  FGSStatus svmSystemPointersSupport_;  //!< The flag for the status of the kernel
                                        //   support of fine-grain system sharing.
  uint32_t  memoryObjOffset_;       //!< The offset of execInfo
  uint32_t  samplerObjOffset_;      //!< The offset of execInfo
  uint32_t  queueObjOffset_;        //!< The offset of execInfo
  amd::Memory** memoryObjects_;     //!< The non argument svm pointers for kernel
  amd::Sampler** samplerObjects_;   //!< The non argument svm pointers for kernel
  amd::DeviceQueue** queueObjects_; //!< The non argument svm pointers for kernel

  uint32_t  totalSize_;             //!< The total size of all captured parameters

  struct {
    uint32_t validated_ : 1;     //!< True if all parameters are defined.
    uint32_t execNewVcop_ : 1;   //!< special new VCOP for kernel execution
    uint32_t execPfpaVcop_ : 1;  //!< special PFPA VCOP for kernel execution
    uint32_t unused : 29;        //!< unused
  };

 public:
  //! Construct a new instance of parameters for the given signature.
  KernelParameters(KernelSignature& signature)
      : signature_(signature),
        execInfoOffset_(0),
        svmSystemPointersSupport_(FGS_DEFAULT),
        memoryObjects_(nullptr),
        samplerObjects_(nullptr),
        queueObjects_(nullptr),
        validated_(0),
        execNewVcop_(0),
        execPfpaVcop_(0) {
    totalSize_ = signature.paramsSize() + (signature.numMemories() +
        signature.numSamplers() + signature.numQueues()) * sizeof(void*);
    values_ = reinterpret_cast<address>(this) + alignUp(sizeof(KernelParameters), 16);
    memoryObjOffset_ = signature_.paramsSize();
    memoryObjects_ = reinterpret_cast<amd::Memory**>(values_ + memoryObjOffset_);
    samplerObjOffset_ = memoryObjOffset_ + signature_.numMemories() * sizeof(amd::Memory*);
    samplerObjects_ = reinterpret_cast<amd::Sampler**>(values_ + samplerObjOffset_);
    queueObjOffset_ = samplerObjOffset_ + signature_.numSamplers() * sizeof(amd::Sampler*);
    queueObjects_ = reinterpret_cast<amd::DeviceQueue**>(values_ + queueObjOffset_);
    address limit = reinterpret_cast<address>(&queueObjects_[signature_.numQueues()]);
    ::memset(values_, '\0', limit - values_);
  }

  explicit KernelParameters(const KernelParameters& rhs)
      : signature_(rhs.signature_),
        execInfoOffset_(rhs.execInfoOffset_),
        execSvmPtr_(rhs.execSvmPtr_),
        svmSystemPointersSupport_(rhs.svmSystemPointersSupport_),
        memoryObjects_(nullptr),
        samplerObjects_(nullptr),
        queueObjects_(nullptr),
        totalSize_(rhs.totalSize_),
        validated_(rhs.validated_),
        execNewVcop_(rhs.execNewVcop_),
        execPfpaVcop_(rhs.execPfpaVcop_) {
    values_ = reinterpret_cast<address>(this) + alignUp(sizeof(KernelParameters), 16);
    memoryObjOffset_ = signature_.paramsSize();
    memoryObjects_ = reinterpret_cast<amd::Memory**>(values_ + memoryObjOffset_);
    samplerObjOffset_ = memoryObjOffset_ + signature_.numMemories() * sizeof(amd::Memory*);
    samplerObjects_ = reinterpret_cast<amd::Sampler**>(values_ + samplerObjOffset_);
    queueObjOffset_ = samplerObjOffset_ + signature_.numSamplers() * sizeof(amd::Sampler*);
    queueObjects_ = reinterpret_cast<amd::DeviceQueue**>(values_ + queueObjOffset_);
    address limit = reinterpret_cast<address>(&queueObjects_[signature_.numQueues()]);
    ::memcpy(values_, rhs.values_, limit - values_);
  }

  //! Reset the parameter at the given \a index (becomes undefined).
  void reset(size_t index) {
    signature_.params()[index].info_.defined_ = false;
    validated_ = 0;
  }
  //! Set the parameter at the given \a index to the value pointed by \a value
  // \a svmBound indicates that \a value is a SVM pointer.
  void set(size_t index, size_t size, const void* value, bool svmBound = false);

  //! Return true if the parameter at the given \a index is defined.
  bool test(size_t index) const { return signature_.at(index).info_.defined_; }

  //! Return true if all the parameters have been defined.
  bool check();

  //! The amount of memory required for local memory needed
  size_t localMemSize(size_t minDataTypeAlignment) const;

  //! Capture the state of the parameters and return the stack base pointer.
  address capture(const Device& device, cl_int* error);
  //! Release the captured state of the parameters.
  void release(address parameters, const amd::Device& device) const;

  //! Allocate memory for this instance as well as the required storage for
  //  the values_, defined_, and rawPointer_ arrays.
  void* operator new(size_t size, const KernelSignature& signature) {
    size_t requiredSize = alignUp(size, 16) + signature.paramsSize() +
      (signature.numMemories() + signature.numSamplers() + signature.numQueues()) *
       sizeof(void*);
    return AlignedMemory::allocate(requiredSize, PARAMETERS_MIN_ALIGNMENT);
  }
  //! Deallocate the memory reserved for this instance.
  void operator delete(void* ptr) { AlignedMemory::deallocate(ptr); }

  //! Deallocate the memory reserved for this instance,
  // matching overloaded operator new.
  void operator delete(void* ptr, const KernelSignature& signature) {
    AlignedMemory::deallocate(ptr);
  }

  //! Returns raw kernel parameters without capture
  address values() const { return values_; }

  //! Return true if the captured parameter at the given \a index is bound to
  // SVM pointer.
  bool boundToSvmPointer(const Device& device, const_address capturedAddress, size_t index) const;
  //! add the svmPtr execInfo into container
  void addSvmPtr(void* const* execInfoArray, size_t count) {
    execSvmPtr_.clear();
    for (size_t i = 0; i < count; i++) {
      execSvmPtr_.push_back(execInfoArray[i]);
    }
  }
  //! get the number of svmPtr in the execInfo container
  size_t getNumberOfSvmPtr() const { return execSvmPtr_.size(); }

  //! get the offset of svmPtr in the parameters
  uint32_t getExecInfoOffset() const { return execInfoOffset_; }

  //! get the offset of memory objects in the parameters
  uint32_t memoryObjOffset() const { return memoryObjOffset_; }

  //! get the offset of sampler objects in the parameters
  uint32_t samplerObjOffset() const { return samplerObjOffset_; }

  //! get the offset of memory objects in the parameters
  uint32_t queueObjOffset() const { return queueObjOffset_; }

  //! set the status of kernel support fine-grained SVM system pointer sharing
  void setSvmSystemPointersSupport(FGSStatus svmSystemSupport) {
    svmSystemPointersSupport_ = svmSystemSupport;
  }

  //! return the status of kernel support fine-grained SVM system pointer sharing
  FGSStatus getSvmSystemPointersSupport() const { return svmSystemPointersSupport_; }

  //! set the new VCOP in the execInfo container
  void setExecNewVcop(const bool newVcop) { execNewVcop_ = (newVcop == true); }

  //! set the PFPA VCOP in the execInfo container
  void setExecPfpaVcop(const bool pfpaVcop) { execPfpaVcop_ = (pfpaVcop == true); }

  //! get the new VCOP in the execInfo container
  bool getExecNewVcop() const { return (execNewVcop_ == 1); }

  //! get the PFPA VCOP in the execInfo container
  bool getExecPfpaVcop() const { return (execPfpaVcop_ == 1); }
};

/*! \brief Encapsulates a __kernel function and the argument values
 *  to be used when invoking this function.
 */
class Kernel : public RuntimeObject {
 private:
  //! The program where this kernel is defined.
  SharedReference<Program> program_;

  const Symbol& symbol_;          //!< The symbol for this kernel.
  std::string name_;              //!< The kernel's name.
  KernelParameters* parameters_;  //!< The parameters.

 protected:
  //! Destroy this kernel
  ~Kernel();

 public:
  /*! \brief Construct a kernel object from the __kernel function
   *  \a kernelName in the given \a program.
   */
  Kernel(Program& program, const Symbol& symbol, const std::string& name);

  //! Construct a new kernel object from an existing one. Used by CloneKernel.
  explicit Kernel(const Kernel& rhs);

  //! Return the program containing this kernel.
  Program& program() const { return program_(); }

  //! Return this kernel's signature.
  const KernelSignature& signature() const;

  //! Return the kernel entry point for the given device.
  const device::Kernel* getDeviceKernel(const Device& device  //!< Device object
                                        ) const;

  //! Return the parameters.
  KernelParameters& parameters() const { return *parameters_; }

  //! Return the kernel's name.
  const std::string& name() const { return name_; }

  virtual ObjectType objectType() const { return ObjectTypeKernel; }
};

/*! @}
 *  @}
 */

}  // namespace amd

#endif /*KERNEL_HPP_*/
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreCompositorChain.h"
#include "OgreCompositionTechnique.h"
#include "OgreCompositorInstance.h"
#include "OgreCompositionTargetPass.h"
#include "OgreCompositionPass.h"
#include "OgreViewport.h"
#include "OgreCamera.h"
#include "OgreRenderTarget.h"
#include "OgreLogManager.h"
#include "OgreCompositorManager.h"
#include "OgreSceneManager.h"
#include "OgreRenderQueueInvocation.h"
namespace Ogre {
CompositorChain::CompositorChain(Viewport *vp):
    mViewport(vp),
	mOriginalScene(0),
    mDirty(true),
	mAnyCompositorsEnabled(false)
{
	mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
    assert(mViewport);
}
//-----------------------------------------------------------------------
CompositorChain::~CompositorChain()
{
	destroyResources();
}
//-----------------------------------------------------------------------
void CompositorChain::destroyResources(void)
{
	clearCompiledState();

	if (mViewport)
	{
		removeAllCompositors();
		mViewport->getTarget()->removeListener(this);
		/// Destroy "original scene" compositor instance
		if (mOriginalScene)
		{
			mOriginalScene->getTechnique()->destroyInstance(mOriginalScene);
			mOriginalScene = 0;
		}
		mViewport = 0;
	}
}
//-----------------------------------------------------------------------
CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, size_t technique)
{
	// Init on demand
	if (!mOriginalScene)
	{
		mViewport->getTarget()->addListener(this);

		/// Create base "original scene" compositor
		CompositorPtr base = CompositorManager::getSingleton().load("Ogre/Scene",
			ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
		mOriginalScene = base->getSupportedTechnique(0)->createInstance(this);
	}

	filter->touch();
    if(technique >= filter->getNumSupportedTechniques())
    {
        /// Warn user
        LogManager::getSingleton().logMessage(
            "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
        );
        return 0;
    }
    CompositionTechnique *tech = filter->getSupportedTechnique(technique);
    CompositorInstance *t = tech->createInstance(this);

    if(addPosition == LAST)
        addPosition = mInstances.size();
    else
        assert(addPosition <= mInstances.size() && "Index out of bounds.");
    mInstances.insert(mInstances.begin()+addPosition, t);

    mDirty = true;
	mAnyCompositorsEnabled = true;
    return t;
}
//-----------------------------------------------------------------------
void CompositorChain::removeCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    Instances::iterator i = mInstances.begin() + index;
    (*i)->getTechnique()->destroyInstance(*i);
    mInstances.erase(i);

    mDirty = true;
}
//-----------------------------------------------------------------------
size_t CompositorChain::getNumCompositors()
{
    return mInstances.size();
}
//-----------------------------------------------------------------------
void CompositorChain::removeAllCompositors()
{
    Instances::iterator i, iend;
    iend = mInstances.end();
    for (i = mInstances.begin(); i != iend; ++i)
    {
        (*i)->getTechnique()->destroyInstance(*i);
    }
    mInstances.clear();

    mDirty = true;
}
//-----------------------------------------------------------------------
void CompositorChain::_removeInstance(CompositorInstance *i)
{
	mInstances.erase(std::find(mInstances.begin(), mInstances.end(), i));
	i->getTechnique()->destroyInstance(i);
}
//-----------------------------------------------------------------------
void CompositorChain::_queuedOperation(CompositorInstance::RenderSystemOperation* op)
{
	mRenderSystemOperations.push_back(op);

}
//-----------------------------------------------------------------------
CompositorInstance *CompositorChain::getCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    return mInstances[index];
}

//-----------------------------------------------------------------------
CompositorChain::InstanceIterator CompositorChain::getCompositors()
{
    return InstanceIterator(mInstances.begin(), mInstances.end());
}
//-----------------------------------------------------------------------
void CompositorChain::setCompositorEnabled(size_t position, bool state)
{
    getCompositor(position)->setEnabled(state);
}
//-----------------------------------------------------------------------
void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	/// Compile if state is dirty
	if(mDirty)
		_compile();

	// Do nothing if no compositors enabled
	if (!mAnyCompositorsEnabled)
	{
		return;
	}

	/// Update dependent render targets; this is done in the preRenderTarget
	/// and not the preViewportUpdate for a reason: at this time, the
	/// target Rendertarget will not yet have been set as current.
	/// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
	/// order would be screwed up and problems would arise with copying rendertextures.
    Camera *cam = mViewport->getCamera();
    /// Iterate over compiled state
    CompositorInstance::CompiledState::iterator i;
    for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
    {
		/// Skip if this is a target that should only be initialised initially
		if(i->onlyInitial && i->hasBeenRendered)
			continue;
		i->hasBeenRendered = true;
		/// Setup and render
        preTargetOperation(*i, i->target->getViewport(0), cam);
        i->target->update();
        postTargetOperation(*i, i->target->getViewport(0), cam);
    }
}
//-----------------------------------------------------------------------
void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only set up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	// set original scene details from viewport
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	CompositionTargetPass* passParent = pass->getParent();
	if (pass->getClearBuffers() != mViewport->getClearBuffers() ||
		pass->getClearColour() != mViewport->getBackgroundColour() ||
		passParent->getVisibilityMask() != mViewport->getVisibilityMask() ||
		passParent->getMaterialScheme() != mViewport->getMaterialScheme() ||
		passParent->getShadowsEnabled() != mViewport->getShadowsEnabled())
	{
		// recompile if viewport settings are different
		pass->setClearBuffers(mViewport->getClearBuffers());
		pass->setClearColour(mViewport->getBackgroundColour());
		passParent->setVisibilityMask(mViewport->getVisibilityMask());
		passParent->setMaterialScheme(mViewport->getMaterialScheme());
		passParent->setShadowsEnabled(mViewport->getShadowsEnabled());
		_compile();
	}

	Camera *cam = mViewport->getCamera();
	/// Prepare for output operation
	preTargetOperation(mOutputOperation, mViewport, cam);
}
//-----------------------------------------------------------------------
void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Set up render target listener
	mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
	mOurListener.notifyViewport(vp);
	/// Register it
	sm->addRenderQueueListener(&mOurListener);
	/// Set visiblity mask
	mOldVisibilityMask = sm->getVisibilityMask();
	sm->setVisibilityMask(op.visibilityMask);
	/// Set whether we find visibles
	mOldFindVisibleObjects = sm->getFindVisibleObjects();
	sm->setFindVisibleObjects(op.findVisibleObjects);
    /// Set LOD bias level
    mOldLodBias = cam->getLodBias();
    cam->setLodBias(cam->getLodBias() * op.lodBias);
	/// Set material scheme
	mOldMaterialScheme = vp->getMaterialScheme();
	vp->setMaterialScheme(op.materialScheme);
	/// Set shadows enabled
	mOldShadowsEnabled = vp->getShadowsEnabled();
	vp->setShadowsEnabled(op.shadowsEnabled);
    /// XXX TODO
    //vp->setClearEveryFrame( true );
    //vp->setOverlaysEnabled( false );
    //vp->setBackgroundColour( op.clearColour );
}
//-----------------------------------------------------------------------
void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Unregister our listener
	sm->removeRenderQueueListener(&mOurListener);
	/// Flush remaing operations
	mOurListener.flushUpTo((uint8)RENDER_QUEUE_COUNT);
	/// Restore default scene and camera settings
	sm->setVisibilityMask(mOldVisibilityMask);
	sm->setFindVisibleObjects(mOldFindVisibleObjects);
    cam->setLodBias(mOldLodBias);
	vp->setMaterialScheme(mOldMaterialScheme);
	vp->setShadowsEnabled(mOldShadowsEnabled);
}
//-----------------------------------------------------------------------
void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only tidy up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	postTargetOperation(mOutputOperation, mViewport, mViewport->getCamera());
}
//-----------------------------------------------------------------------
void CompositorChain::viewportRemoved(const RenderTargetViewportEvent& evt)
{
	// check this is the viewport we're attached to (multi-viewport targets)
	if (evt.source == mViewport)
	{
		// this chain is now orphaned
		// can't delete it since held from outside, but release all resources being used
		destroyResources();
	}

}
//-----------------------------------------------------------------------
void CompositorChain::clearCompiledState()
{
	for (RenderSystemOperations::iterator i = mRenderSystemOperations.begin();
		i != mRenderSystemOperations.end(); ++i)
	{
		OGRE_DELETE *i;
	}
	mRenderSystemOperations.clear();

	/// Clear compiled state
	mCompiledState.clear();
	mOutputOperation = CompositorInstance::TargetOperation(0);

}
//-----------------------------------------------------------------------
void CompositorChain::_compile()
{
	clearCompiledState();

	bool compositorsEnabled = false;

    /// Set previous CompositorInstance for each compositor in the list
    CompositorInstance *lastComposition = mOriginalScene;
	mOriginalScene->mPreviousInstance = 0;
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	pass->setClearBuffers(mViewport->getClearBuffers());
	pass->setClearColour(mViewport->getBackgroundColour());
    for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
    {
        if((*i)->getEnabled())
        {
			compositorsEnabled = true;
            (*i)->mPreviousInstance = lastComposition;
            lastComposition = (*i);
        }
    }

    /// Compile misc targets
    lastComposition->_compileTargetOperations(mCompiledState);

    /// Final target viewport (0)
	mOutputOperation.renderSystemOperations.clear();
    lastComposition->_compileOutputOperation(mOutputOperation);

	// Deal with viewport settings
	if (compositorsEnabled != mAnyCompositorsEnabled)
	{
		mAnyCompositorsEnabled = compositorsEnabled;
		if (mAnyCompositorsEnabled)
		{
			// Save old viewport clearing options
			mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
			// Don't clear anything every frame since we have our own clear ops
			mViewport->setClearEveryFrame(false);
		}
		else
		{
			// Reset clearing options
			mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
				mOldClearEveryFrameBuffers);
		}
	}

    mDirty = false;
}
//-----------------------------------------------------------------------
void CompositorChain::_markDirty()
{
    mDirty = true;
}
//-----------------------------------------------------------------------
Viewport *CompositorChain::getViewport()
{
    return mViewport;
}
//---------------------------------------------------------------------
void CompositorChain::_notifyViewport(Viewport* vp)
{
	mViewport = vp;
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueStarted(uint8 id,
	const String& invocation, bool& skipThisQueue)
{
	// Skip when not matching viewport
	// shadows update is nested within main viewport update
	if (mSceneManager->getCurrentViewport() != mViewport)
		return;

	flushUpTo(id);
	/// If noone wants to render this queue, skip it
	/// Don't skip the OVERLAY queue because that's handled seperately
	if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
	{
		skipThisQueue = true;
	}
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueEnded(uint8 id,
	const String& invocation, bool& repeatThisQueue)
{
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
{
	mOperation = op;
	mSceneManager = sm;
	mRenderSystem = rs;
	currentOp = op->renderSystemOperations.begin();
	lastOp = op->renderSystemOperations.end();
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::flushUpTo(uint8 id)
{
	/// Process all RenderSystemOperations up to and including render queue id.
    /// Including, because the operations for RenderQueueGroup x should be executed
	/// at the beginning of the RenderQueueGroup render for x.
	while(currentOp != lastOp && currentOp->first <= id)
	{
		currentOp->second->execute(mSceneManager, mRenderSystem);
		++currentOp;
	}
}
//-----------------------------------------------------------------------
}
<commit_msg>Remove flushUpTo() call in CompositorChain::postTargetOperation; this happens after the begin/end of the scene and actually gets ignored anyway, D3D9 would bitch about this in debug mode<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreCompositorChain.h"
#include "OgreCompositionTechnique.h"
#include "OgreCompositorInstance.h"
#include "OgreCompositionTargetPass.h"
#include "OgreCompositionPass.h"
#include "OgreViewport.h"
#include "OgreCamera.h"
#include "OgreRenderTarget.h"
#include "OgreLogManager.h"
#include "OgreCompositorManager.h"
#include "OgreSceneManager.h"
#include "OgreRenderQueueInvocation.h"
namespace Ogre {
CompositorChain::CompositorChain(Viewport *vp):
    mViewport(vp),
	mOriginalScene(0),
    mDirty(true),
	mAnyCompositorsEnabled(false)
{
	mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
    assert(mViewport);
}
//-----------------------------------------------------------------------
CompositorChain::~CompositorChain()
{
	destroyResources();
}
//-----------------------------------------------------------------------
void CompositorChain::destroyResources(void)
{
	clearCompiledState();

	if (mViewport)
	{
		removeAllCompositors();
		mViewport->getTarget()->removeListener(this);
		/// Destroy "original scene" compositor instance
		if (mOriginalScene)
		{
			mOriginalScene->getTechnique()->destroyInstance(mOriginalScene);
			mOriginalScene = 0;
		}
		mViewport = 0;
	}
}
//-----------------------------------------------------------------------
CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, size_t technique)
{
	// Init on demand
	if (!mOriginalScene)
	{
		mViewport->getTarget()->addListener(this);

		/// Create base "original scene" compositor
		CompositorPtr base = CompositorManager::getSingleton().load("Ogre/Scene",
			ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
		mOriginalScene = base->getSupportedTechnique(0)->createInstance(this);
	}

	filter->touch();
    if(technique >= filter->getNumSupportedTechniques())
    {
        /// Warn user
        LogManager::getSingleton().logMessage(
            "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
        );
        return 0;
    }
    CompositionTechnique *tech = filter->getSupportedTechnique(technique);
    CompositorInstance *t = tech->createInstance(this);

    if(addPosition == LAST)
        addPosition = mInstances.size();
    else
        assert(addPosition <= mInstances.size() && "Index out of bounds.");
    mInstances.insert(mInstances.begin()+addPosition, t);

    mDirty = true;
	mAnyCompositorsEnabled = true;
    return t;
}
//-----------------------------------------------------------------------
void CompositorChain::removeCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    Instances::iterator i = mInstances.begin() + index;
    (*i)->getTechnique()->destroyInstance(*i);
    mInstances.erase(i);

    mDirty = true;
}
//-----------------------------------------------------------------------
size_t CompositorChain::getNumCompositors()
{
    return mInstances.size();
}
//-----------------------------------------------------------------------
void CompositorChain::removeAllCompositors()
{
    Instances::iterator i, iend;
    iend = mInstances.end();
    for (i = mInstances.begin(); i != iend; ++i)
    {
        (*i)->getTechnique()->destroyInstance(*i);
    }
    mInstances.clear();

    mDirty = true;
}
//-----------------------------------------------------------------------
void CompositorChain::_removeInstance(CompositorInstance *i)
{
	mInstances.erase(std::find(mInstances.begin(), mInstances.end(), i));
	i->getTechnique()->destroyInstance(i);
}
//-----------------------------------------------------------------------
void CompositorChain::_queuedOperation(CompositorInstance::RenderSystemOperation* op)
{
	mRenderSystemOperations.push_back(op);

}
//-----------------------------------------------------------------------
CompositorInstance *CompositorChain::getCompositor(size_t index)
{
    assert (index < mInstances.size() && "Index out of bounds.");
    return mInstances[index];
}

//-----------------------------------------------------------------------
CompositorChain::InstanceIterator CompositorChain::getCompositors()
{
    return InstanceIterator(mInstances.begin(), mInstances.end());
}
//-----------------------------------------------------------------------
void CompositorChain::setCompositorEnabled(size_t position, bool state)
{
    getCompositor(position)->setEnabled(state);
}
//-----------------------------------------------------------------------
void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	/// Compile if state is dirty
	if(mDirty)
		_compile();

	// Do nothing if no compositors enabled
	if (!mAnyCompositorsEnabled)
	{
		return;
	}

	/// Update dependent render targets; this is done in the preRenderTarget
	/// and not the preViewportUpdate for a reason: at this time, the
	/// target Rendertarget will not yet have been set as current.
	/// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
	/// order would be screwed up and problems would arise with copying rendertextures.
    Camera *cam = mViewport->getCamera();
    /// Iterate over compiled state
    CompositorInstance::CompiledState::iterator i;
    for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
    {
		/// Skip if this is a target that should only be initialised initially
		if(i->onlyInitial && i->hasBeenRendered)
			continue;
		i->hasBeenRendered = true;
		/// Setup and render
        preTargetOperation(*i, i->target->getViewport(0), cam);
        i->target->update();
        postTargetOperation(*i, i->target->getViewport(0), cam);
    }
}
//-----------------------------------------------------------------------
void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only set up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	// set original scene details from viewport
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	CompositionTargetPass* passParent = pass->getParent();
	if (pass->getClearBuffers() != mViewport->getClearBuffers() ||
		pass->getClearColour() != mViewport->getBackgroundColour() ||
		passParent->getVisibilityMask() != mViewport->getVisibilityMask() ||
		passParent->getMaterialScheme() != mViewport->getMaterialScheme() ||
		passParent->getShadowsEnabled() != mViewport->getShadowsEnabled())
	{
		// recompile if viewport settings are different
		pass->setClearBuffers(mViewport->getClearBuffers());
		pass->setClearColour(mViewport->getBackgroundColour());
		passParent->setVisibilityMask(mViewport->getVisibilityMask());
		passParent->setMaterialScheme(mViewport->getMaterialScheme());
		passParent->setShadowsEnabled(mViewport->getShadowsEnabled());
		_compile();
	}

	Camera *cam = mViewport->getCamera();
	/// Prepare for output operation
	preTargetOperation(mOutputOperation, mViewport, cam);
}
//-----------------------------------------------------------------------
void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Set up render target listener
	mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
	mOurListener.notifyViewport(vp);
	/// Register it
	sm->addRenderQueueListener(&mOurListener);
	/// Set visiblity mask
	mOldVisibilityMask = sm->getVisibilityMask();
	sm->setVisibilityMask(op.visibilityMask);
	/// Set whether we find visibles
	mOldFindVisibleObjects = sm->getFindVisibleObjects();
	sm->setFindVisibleObjects(op.findVisibleObjects);
    /// Set LOD bias level
    mOldLodBias = cam->getLodBias();
    cam->setLodBias(cam->getLodBias() * op.lodBias);
	/// Set material scheme
	mOldMaterialScheme = vp->getMaterialScheme();
	vp->setMaterialScheme(op.materialScheme);
	/// Set shadows enabled
	mOldShadowsEnabled = vp->getShadowsEnabled();
	vp->setShadowsEnabled(op.shadowsEnabled);
    /// XXX TODO
    //vp->setClearEveryFrame( true );
    //vp->setOverlaysEnabled( false );
    //vp->setBackgroundColour( op.clearColour );
}
//-----------------------------------------------------------------------
void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
{
    SceneManager *sm = cam->getSceneManager();
	/// Unregister our listener
	sm->removeRenderQueueListener(&mOurListener);
	/// Restore default scene and camera settings
	sm->setVisibilityMask(mOldVisibilityMask);
	sm->setFindVisibleObjects(mOldFindVisibleObjects);
    cam->setLodBias(mOldLodBias);
	vp->setMaterialScheme(mOldMaterialScheme);
	vp->setShadowsEnabled(mOldShadowsEnabled);
}
//-----------------------------------------------------------------------
void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
{
	// Only tidy up if there is at least one compositor enabled, and it's this viewport
    if(evt.source != mViewport || !mAnyCompositorsEnabled)
        return;

	postTargetOperation(mOutputOperation, mViewport, mViewport->getCamera());
}
//-----------------------------------------------------------------------
void CompositorChain::viewportRemoved(const RenderTargetViewportEvent& evt)
{
	// check this is the viewport we're attached to (multi-viewport targets)
	if (evt.source == mViewport)
	{
		// this chain is now orphaned
		// can't delete it since held from outside, but release all resources being used
		destroyResources();
	}

}
//-----------------------------------------------------------------------
void CompositorChain::clearCompiledState()
{
	for (RenderSystemOperations::iterator i = mRenderSystemOperations.begin();
		i != mRenderSystemOperations.end(); ++i)
	{
		OGRE_DELETE *i;
	}
	mRenderSystemOperations.clear();

	/// Clear compiled state
	mCompiledState.clear();
	mOutputOperation = CompositorInstance::TargetOperation(0);

}
//-----------------------------------------------------------------------
void CompositorChain::_compile()
{
	clearCompiledState();

	bool compositorsEnabled = false;

    /// Set previous CompositorInstance for each compositor in the list
    CompositorInstance *lastComposition = mOriginalScene;
	mOriginalScene->mPreviousInstance = 0;
	CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPass(0);
	pass->setClearBuffers(mViewport->getClearBuffers());
	pass->setClearColour(mViewport->getBackgroundColour());
    for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
    {
        if((*i)->getEnabled())
        {
			compositorsEnabled = true;
            (*i)->mPreviousInstance = lastComposition;
            lastComposition = (*i);
        }
    }

    /// Compile misc targets
    lastComposition->_compileTargetOperations(mCompiledState);

    /// Final target viewport (0)
	mOutputOperation.renderSystemOperations.clear();
    lastComposition->_compileOutputOperation(mOutputOperation);

	// Deal with viewport settings
	if (compositorsEnabled != mAnyCompositorsEnabled)
	{
		mAnyCompositorsEnabled = compositorsEnabled;
		if (mAnyCompositorsEnabled)
		{
			// Save old viewport clearing options
			mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
			// Don't clear anything every frame since we have our own clear ops
			mViewport->setClearEveryFrame(false);
		}
		else
		{
			// Reset clearing options
			mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
				mOldClearEveryFrameBuffers);
		}
	}

    mDirty = false;
}
//-----------------------------------------------------------------------
void CompositorChain::_markDirty()
{
    mDirty = true;
}
//-----------------------------------------------------------------------
Viewport *CompositorChain::getViewport()
{
    return mViewport;
}
//---------------------------------------------------------------------
void CompositorChain::_notifyViewport(Viewport* vp)
{
	mViewport = vp;
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueStarted(uint8 id,
	const String& invocation, bool& skipThisQueue)
{
	// Skip when not matching viewport
	// shadows update is nested within main viewport update
	if (mSceneManager->getCurrentViewport() != mViewport)
		return;

	flushUpTo(id);
	/// If noone wants to render this queue, skip it
	/// Don't skip the OVERLAY queue because that's handled seperately
	if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
	{
		skipThisQueue = true;
	}
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::renderQueueEnded(uint8 id,
	const String& invocation, bool& repeatThisQueue)
{
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
{
	mOperation = op;
	mSceneManager = sm;
	mRenderSystem = rs;
	currentOp = op->renderSystemOperations.begin();
	lastOp = op->renderSystemOperations.end();
}
//-----------------------------------------------------------------------
void CompositorChain::RQListener::flushUpTo(uint8 id)
{
	/// Process all RenderSystemOperations up to and including render queue id.
    /// Including, because the operations for RenderQueueGroup x should be executed
	/// at the beginning of the RenderQueueGroup render for x.
	while(currentOp != lastOp && currentOp->first <= id)
	{
		currentOp->second->execute(mSceneManager, mRenderSystem);
		++currentOp;
	}
}
//-----------------------------------------------------------------------
}
<|endoftext|>


<commit_before>
#include <assert.h>
#include <sys/time.h>

#include <iostream>
#include <fstream>

#include "PomdpM.h"
#include "MatrixUtils.h"
#include "FocusedPomdp.h"
#if USE_EMPOMDP
#  include "EMPomdp.h"
#endif
#include "Interleave.h"
#include "stdinInterface.h"

using namespace std;
using namespace MatrixUtils;

void usage(void) {
  cerr <<
    "usage: testPomdp OPTIONS <algorithm> <probname> [minOrder maxOrder]\n"
    "  -h or --help       Print this help\n"
    "  -f or --fast       Use fast (but very picky) alternate parser\n"
    "  -i or --iterations Set number of simulation iterations (default: 1000)\n"
    "  -n or --no-console Do not poll for user console commands\n"
    "\n"
    "  available algorithms:\n"
    "    hsvi\n"
#if USE_EMPOMDP
    "    empomdp\n"
#endif
;
  exit(-1);
}

void testBatchIncremental(string algorithm,
			  string prob_name,
			  int min_order,
			  int max_order,
			  int num_iterations,
			  bool use_fast_parser)
{
  PomdpM problem;

  cout << "CFLAGS = " << CFLAGS << endl;

  //prob_name = "examples/" + prob_name + ".pomdp";
  problem.readFromFile( prob_name, use_fast_parser );

#if 0
  // test benchmark code

  cout << "numStates = " << problem.numStates << endl;
  cout << "T.size = " << problem.T[4].size1()
       << " " << problem.T[4].size2() << endl;

  timeval startTime, endTime;
  belief_vector result(problem.numStates);
  bmatrix& T = problem.T[4];
  belief_vector& b0 = problem.initialBelief;
  dvector tmp(problem.numStates);

  gettimeofday(&startTime,0);
  for (int i=0; i < 10; i++) {
    //noalias(result) = prod( T, b0 );
    axpy_prod( T, b0, tmp, true );
    result = tmp;
  }
  gettimeofday(&endTime,0);

  cout << "multiplies: elapsed time = "
       << ((endTime.tv_sec - startTime.tv_sec)
	   + 1e-6*(endTime.tv_usec - startTime.tv_usec))
       << endl;

  const char* fname = "result_tp.dat";
  ofstream out(fname);
  if (!out) {
    cerr << "ERROR: couldn't open " << fname << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  out << problem.numStates << endl;
  FOR (i, problem.numStates) {
    out << result[i] << endl;
  }
  out.close();

  exit(0);
#endif

  Solver* solver;
  if (0) {
  }
  else if (algorithm == "hsvi") {
    solver = new FocusedPomdp();
  }
#if USE_EMPOMDP
  else if (algorithm == "empomdp") {
    solver = new EMPomdp();
  }
#endif
  else {
    cerr << "ERROR: unknown algorithm " << algorithm << endl << endl;
    usage();
  }

  //string prefix = "/tmp/";
  string prefix = "";
  Interleave x;
  x.batchTestIncremental(/* numIterations = */ num_iterations,
			 &problem, *solver,
			 /* numSteps = */ 251,
			 /* minPrecision = */ 1e-10,
			 /* minOrder = */ min_order,
			 /* maxOrder = */ max_order,
			 /* ticksPerOrder = */ 3,
			 /* outFileName = */ "inc.plot",
			 /* boundsFileName = */ "bounds.plot",
			 /* simFileName = */ "sim.plot");

  x.printRewards();
}

int main(int argc, char **argv) {
  init_matrix_utils();

  char *algorithm = NULL;
  char *prob_name = NULL;
  int min_order = -1;
  int max_order = -1;
  bool use_fast_parser = false;
  int num_iterations = 1000;

  for (int argi=1; argi < argc; argi++) {
    string args = argv[argi];
    if (args[0] == '-') {
      if (args == "-h" || args == "--help") {
	usage();
      } else if (args == "-f" || args == "--fast") {
	use_fast_parser = true;
      } else if (args == "-i" || args == "--iterations") {
	if (++argi == argc) {
	  cerr << "ERROR: -i flag without argument" << endl;
	}
	num_iterations = atoi(argv[argi]);
      } else if (args == "-n" || args == "--no-console") {
	setPollingEnabled(0);
      } else {
	cerr << "ERROR: unknown option " << args << endl << endl;
	usage();
      }
    } else if (algorithm == NULL) {
      algorithm = argv[argi];
    } else if (prob_name == NULL) {
      prob_name = argv[argi];
    } else if (min_order == -1) {
      min_order = atoi(argv[argi]);
    } else if (max_order == -1) {
      max_order = atoi(argv[argi]);
    } else {
      cerr << "ERROR: too many arguments" << endl << endl;
      usage();
    }
  }

  if (prob_name == NULL) {
    cerr << "ERROR: not enough arguments" << endl << endl;
    usage();
  }
  if (min_order == -1) {
    min_order = 0; // default
  }
  if (max_order == -1) {
    max_order = 6; // default
  }

  testBatchIncremental(algorithm, prob_name, min_order, max_order,
		       num_iterations, use_fast_parser);

  // signal we are done
  FILE *fp = fopen("/tmp/testPomdp_done", "w");
  fprintf(fp, "success\n");
  fclose(fp);

  return 0;
}
<commit_msg>added support for negative min_order/max_order and for qmdp algorithm<commit_after>
#include <assert.h>
#include <sys/time.h>

#include <iostream>
#include <fstream>

#include "PomdpM.h"
#include "FocusedPomdp.h"
#if USE_EMPOMDP
#  include "EMPomdp.h"
#endif
#include "QMDP.h"
#include "Interleave.h"
#include "stdinInterface.h"

using namespace std;
using namespace MatrixUtils;

void usage(void) {
  cerr <<
    "usage: testPomdp OPTIONS <algorithm> <probname> [minOrder maxOrder]\n"
    "  -h or --help       Print this help\n"
    "  --version          Print version information\n"
    "  -f or --fast       Use fast (but very picky) alternate problem parser\n"
    "  -i or --iterations Set number of simulation iterations (default: 1000)\n"
    "  -n or --no-console Do not poll for user console commands\n"
    "\n"
    "  available algorithms:\n"
    "    hsvi\n"
#if USE_EMPOMDP
    "    empomdp\n"
#endif
    "    qmdp\n"
;
  exit(-1);
}

void testBatchIncremental(string algorithm,
			  string prob_name,
			  int min_order,
			  int max_order,
			  int num_iterations,
			  bool use_fast_parser)
{
  PomdpM problem;

  cout << "CFLAGS = " << CFLAGS << endl;

  //prob_name = "examples/" + prob_name + ".pomdp";
  problem.readFromFile( prob_name, use_fast_parser );

#if 0
  // test benchmark code

  cout << "numStates = " << problem.numStates << endl;
  cout << "T.size = " << problem.T[4].size1()
       << " " << problem.T[4].size2() << endl;

  timeval startTime, endTime;
  belief_vector result(problem.numStates);
  bmatrix& T = problem.T[4];
  belief_vector& b0 = problem.initialBelief;
  dvector tmp(problem.numStates);

  gettimeofday(&startTime,0);
  for (int i=0; i < 10; i++) {
    //noalias(result) = prod( T, b0 );
    axpy_prod( T, b0, tmp, true );
    result = tmp;
  }
  gettimeofday(&endTime,0);

  cout << "multiplies: elapsed time = "
       << ((endTime.tv_sec - startTime.tv_sec)
	   + 1e-6*(endTime.tv_usec - startTime.tv_usec))
       << endl;

  const char* fname = "result_tp.dat";
  ofstream out(fname);
  if (!out) {
    cerr << "ERROR: couldn't open " << fname << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  out << problem.numStates << endl;
  FOR (i, problem.numStates) {
    out << result[i] << endl;
  }
  out.close();

  exit(0);
#endif

  Solver* solver;
  if (0) {
  }
  else if (algorithm == "hsvi") {
    solver = new FocusedPomdp();
  }
#if USE_EMPOMDP
  else if (algorithm == "empomdp") {
    solver = new EMPomdp();
  }
#endif
  else if (algorithm == "qmdp") {
    solver = new QMDP();
  }
  else {
    cerr << "ERROR: unknown algorithm " << algorithm << endl << endl;
    usage();
  }

  //string prefix = "/tmp/";
  string prefix = "";
  Interleave x;
  x.batchTestIncremental(/* numIterations = */ num_iterations,
			 &problem, *solver,
			 /* numSteps = */ 251,
			 /* minPrecision = */ 1e-10,
			 /* minOrder = */ min_order,
			 /* maxOrder = */ max_order,
			 /* ticksPerOrder = */ 3,
			 /* outFileName = */ "inc.plot",
			 /* boundsFileName = */ "bounds.plot",
			 /* simFileName = */ "sim.plot");

  x.printRewards();
}

int main(int argc, char **argv) {
  init_matrix_utils();

  char *algorithm = NULL;
  char *prob_name = NULL;
  int min_order = -999;
  int max_order = -999;
  bool use_fast_parser = false;
  int num_iterations = 1000;
  bool past_options = false;

  for (int argi=1; argi < argc; argi++) {
    string args = argv[argi];
    if (args[0] == '-' && !past_options) {
      if (args == "-h" || args == "--help") {
	usage();
      } else if (args == "--version") {
	cout << "CFLAGS = " << CFLAGS << endl;
	exit(EXIT_SUCCESS);
      } else if (args == "-f" || args == "--fast") {
	use_fast_parser = true;
      } else if (args == "-i" || args == "--iterations") {
	if (++argi == argc) {
	  cerr << "ERROR: -i flag without argument" << endl;
	}
	num_iterations = atoi(argv[argi]);
      } else if (args == "-n" || args == "--no-console") {
	setPollingEnabled(0);
      } else if (args == "--") {
	past_options = true;
	cout << "got --" << endl;
      } else {
	cerr << "ERROR: unknown option " << args << endl << endl;
	usage();
      }
    } else if (algorithm == NULL) {
      algorithm = argv[argi];
    } else if (prob_name == NULL) {
      prob_name = argv[argi];
    } else if (-999 == min_order) {
      min_order = atoi(argv[argi]);
    } else if (-999 == max_order) {
      max_order = atoi(argv[argi]);
    } else {
      cerr << "ERROR: too many arguments" << endl << endl;
      usage();
    }
  }

  if (prob_name == NULL) {
    cerr << "ERROR: not enough arguments" << endl << endl;
    usage();
  }
  if (-999 == min_order) {
    min_order = 0; // default
  }
  if (-999 == max_order) {
    max_order = 6; // default
  }

  testBatchIncremental(algorithm, prob_name, min_order, max_order,
		       num_iterations, use_fast_parser);

  // signal we are done
  FILE *fp = fopen("/tmp/testPomdp_done", "w");
  fprintf(fp, "success\n");
  fclose(fp);

  return 0;
}
<|endoftext|>