Jump to content

  • Log In with Google      Sign In   
  • Create Account

Tispe

Member Since 02 Oct 2010
Offline Last Active Today, 07:55 PM

#5177820 DX12 - Documentation / Tutorials?

Posted by Tispe on 03 September 2014 - 04:13 AM

Hi

 

 

I wanted to know if anyone here has had the chance to use/look at the Direct3D 12 API?

 

How different is it from DX9, DX11? Is it a whole paradigm shift?

 

Is it the basics: "create buffer -> copy data to buffer -> Draw from buffer" kind of thing?

 

Im mostly just familiar with DX9 and want to catch up with DX12. Should I learn DX11 while waiting for docs/tutorials?

 

Cheers!

 




#5153002 DirectX 9 SetRenderTarget

Posted by Tispe on 11 May 2014 - 11:52 PM

Right after you create your device, use use code like this to get a pointer to the "screen" (the default colour target and default depth target).

IDirect3DSurface9* defaultColorBuffer = 0;
IDirect3DSurface9* defaultDepthBuffer = 0;
device->GetRenderTarget( 0, &defaultColorBuffer );
device->GetDepthStencilSurface( &defaultDepthBuffer );

After rendering to a texture, you can use device->SetRenderTarget(defaultColorBuffer) to go back to rendering to the screen.

Yes, SetRenderTarget is the correct way to render to textures wink.png

 

[edit] ninja'ed by LS ph34r.png

 

And those surfaces has to be Released at the end of the program, and also released and reaquired when changing display settings?




#5152568 Four pillars of object oriented programming

Posted by Tispe on 09 May 2014 - 11:57 AM

C++ is a light-weight abstraction programming language. Type- and exception- safety I think is at the core of the language.

 

The constructor acquire resources and the destructor releases them. I believe OOP in C++ is just a consequence of these fundamental principles; OOP is not a design goal in itself.




#5152492 simple win32 hack for user/pass input

Posted by Tispe on 09 May 2014 - 03:00 AM

For those interested:

#include <Windows.h>
#include "Header.h"
#include <string>

LRESULT CALLBACK dlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	std::string* pPass = NULL;

	if(Msg == WM_INITDIALOG)
	{
		SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
	} else {
		pPass = reinterpret_cast<std::string*>(GetWindowLong(hDlg, GWL_USERDATA));
	}

	switch (Msg)
	{
	case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
			case 27:
				{
					wchar_t szItemData[64];
					if (!GetDlgItemText(hDlg, 26, szItemData, 64)) 
						*szItemData=0;

					if(pPass && szItemData)
					{
						std::wstring my(szItemData);
						*pPass = std::string( my.begin(), my.end() );
					}
					EndDialog(hDlg, IDOK);
					return 1;
				}
				break;
			case 28:
				{
					EndDialog(hDlg, IDOK);
					return 1;
				}
				break;
			default:
				break;
			}
			break;
		}
	case WM_CLOSE:
		EndDialog(hDlg, IDOK);
		return 1;
	}

	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	std::string Password;

	DialogTemplate dialogTemplate("Login required!", WS_CAPTION | DS_CENTER, 0, 0, 109, 45, "Tahoma");
	dialogTemplate.AddStatic("User:", WS_VISIBLE, 0, 3, 3, 20, 10, -1);
	dialogTemplate.AddStatic("Pass:", WS_VISIBLE, 0, 3, 16, 20, 10, -1);
	dialogTemplate.AddEditBox("", WS_VISIBLE, WS_EX_STATICEDGE, 25, 3, 81, 10, 25);
	dialogTemplate.AddEditBox("", WS_VISIBLE | ES_PASSWORD, WS_EX_STATICEDGE, 25, 16, 81, 10, 26);
	dialogTemplate.AddButton("Confirm", WS_VISIBLE, 0, 3, 29, 50, 13, 27);
	dialogTemplate.AddButton("Exit", WS_VISIBLE, 0, 56, 29, 50, 13, 28);
	DialogBoxIndirectParam(NULL, dialogTemplate, NULL, (DLGPROC)dlgProc, (LPARAM)&Password);

	MessageBoxA(NULL, Password.c_str(), "Let us see....", 0);
}
#include <windows.h>

class DialogTemplate
{

public:

	DialogTemplate(LPCSTR caption, DWORD style, int x, int y, int w, int h, LPCSTR font = NULL, WORD fontSize = 8)
	{

		usedBufferLength = sizeof(DLGTEMPLATE );
		totalBufferLength = usedBufferLength;

		dialogTemplate = (DLGTEMPLATE*)malloc(totalBufferLength);

		dialogTemplate->style = style;

		if (font != NULL)
		{
			dialogTemplate->style |= DS_SETFONT;
		}

		dialogTemplate->x     = x;
		dialogTemplate->y     = y;
		dialogTemplate->cx    = w;
		dialogTemplate->cy    = h;
		dialogTemplate->cdit  = 0;

		dialogTemplate->dwExtendedStyle = 0;

		// The dialog box doesn't have a menu or a special class

		AppendData(L"\0", 2);
		AppendData(L"\0", 2);

		// Add the dialog's caption to the template

		AppendString(caption);

		if (font != NULL)
		{
			AppendData(&fontSize, sizeof(WORD));
			AppendString(font);
		}

	}

	void AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle,
		int x, int y, int w, int h, WORD id)
	{

		DLGITEMTEMPLATE item;

		item.style = style;
		item.x     = x;
		item.y     = y;
		item.cx    = w;
		item.cy    = h;
		item.id    = id;

		item.dwExtendedStyle = exStyle;

		AppendData(&item, sizeof(DLGITEMTEMPLATE));

		AppendString(type);
		AppendString(caption);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

		// Increment the component count

		dialogTemplate->cdit++;

	}

	void AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0080, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	void AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0081, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	void AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0082, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	void AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0083, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	void AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0084, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	void AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y,
		int w, int h, WORD id)
	{

		AddStandardComponent(0x0085, caption, style, exStyle, x, y, w, h, id);

		WORD creationDataLength = 0;
		AppendData(&creationDataLength, sizeof(WORD));

	}

	/**
	* Returns a pointer to the Win32 dialog template which the object
	* represents. This pointer may become invalid if additional
	* components are added to the template.
	*/

	operator const DLGTEMPLATE*() const
	{
		return dialogTemplate;
	}

	virtual ~DialogTemplate()
	{
		free(dialogTemplate);
	}

protected:

	void AddStandardComponent(WORD type, LPCSTR caption, DWORD style,
		DWORD exStyle, int x, int y, int w, int h, WORD id)
	{

		DLGITEMTEMPLATE item;

		// DWORD algin the beginning of the component data

		AlignData(sizeof(DWORD));

		item.style = style;
		item.x     = x;
		item.y     = y;
		item.cx    = w;
		item.cy    = h;
		item.id    = id;

		item.dwExtendedStyle = exStyle;

		AppendData(&item, sizeof(DLGITEMTEMPLATE));

		WORD preType = 0xFFFF;

		AppendData(&preType, sizeof(WORD));
		AppendData(&type, sizeof(WORD));

		AppendString(caption);

		// Increment the component count

		dialogTemplate->cdit++;

	}

	void AlignData(int size)
	{

		int paddingSize = usedBufferLength % size;

		if (paddingSize != 0)
		{
			EnsureSpace(paddingSize);
			usedBufferLength += paddingSize;
		}

	}

	void AppendString(LPCSTR string)
	{

		int length = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0);

		WCHAR* wideString = (WCHAR*)malloc(sizeof(WCHAR) * length);
		MultiByteToWideChar(CP_ACP, 0, string, -1, wideString, length);

		AppendData(wideString, length * sizeof(WCHAR));
		free(wideString);

	}

	void AppendData(void* data, int dataLength)
	{

		EnsureSpace(dataLength);

		memcpy((char*)dialogTemplate + usedBufferLength, data, dataLength);
		usedBufferLength += dataLength;

	}

	void EnsureSpace(int length)
	{

		if (length + usedBufferLength > totalBufferLength)
		{

			totalBufferLength += length * 2;

			void* newBuffer = malloc(totalBufferLength);
			memcpy(newBuffer, dialogTemplate, usedBufferLength);

			free(dialogTemplate);
			dialogTemplate = (DLGTEMPLATE*)newBuffer;

		}

	}

private:

	DLGTEMPLATE* dialogTemplate;

	int totalBufferLength;
	int usedBufferLength;

};



#5149619 Multithread question

Posted by Tispe on 26 April 2014 - 06:27 AM

Consider pipelining this, so that you have two identical textures which are updated every other frame for maximum utilization. The other thread is updating one texture while the main thread renders from the other.




#5148347 Tips on FileLoader code

Posted by Tispe on 20 April 2014 - 07:10 AM


Just from a coding standard view why are you placing an enter after a function or if conditional and the { and not on an else clause.

 

Well, I just ported to Visual Studio 2013 Express for C++11 support, and the IDE forces that behaviour.... It also wants a space between if and (. Prob someone at MS wants ifs and elses in the same vertical....

 

I thouched up my code, please let me know if it is unsafe:

class FileLoader
{
public:
	FileLoader(std::string Filename, bool Asynchronous);
	~FileLoader();

	FileLoaderCodes GetStatus();

private:
	void Tick();
	void ReadAsynch();
	void ReadSynch();

	HANDLE file;
	FileLoaderCodes Status;
	DWORD Size;
	DWORD NumberOfBytesTransfered;
	DWORD LastError;
	OVERLAPPED OverlappedInfo;
	std::vector<BYTE> buffer;
};
FileLoader::FileLoader(std::string Filename, bool Asynchronous)
{
	Status = FileLoaderCodes::Unknown;
	Size = 0;
	NumberOfBytesTransfered = 0;
	LastError = 0;
	ZeroMemory(&OverlappedInfo, sizeof(OverlappedInfo));

	if (Asynchronous)
	{
		file = CreateFileA(Filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
	}
	else {
		file = CreateFileA(Filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	}

	if (file == INVALID_HANDLE_VALUE)
	{
		LastError = GetLastError();
		Status = FileLoaderCodes::InvalidHandle;
		return;
	}

	Size = GetFileSize(file, NULL);
	if (Size == INVALID_FILE_SIZE)
	{
		LastError = GetLastError();
		Status = FileLoaderCodes::InvalidSize;
		CloseHandle(file);
		return;
	}

	buffer.resize(Size);
	if (buffer.capacity() < Size)
	{
		Status = FileLoaderCodes::AllocError;
		CloseHandle(file);
		return;
	}

	if (Asynchronous)
	{
		ReadAsynch();
	}
	else {
		ReadSynch();
	}

}

FileLoader::~FileLoader()
{
	CloseHandle(file);
}

FileLoaderCodes FileLoader::GetStatus()
{
	Tick();
	return Status;
}

void FileLoader::ReadAsynch()
{
	OverlappedInfo.hEvent = CreateEvent(NULL, true, false, NULL);

	if (OverlappedInfo.hEvent == NULL)
	{
		LastError = GetLastError();
		Status = FileLoaderCodes::CreateEventError;
		CloseHandle(file);
		return;
	}

	if (ReadFile(file, buffer.data(), Size, NULL, &OverlappedInfo))
	{
		// Operation has completed immediately.
		Status = FileLoaderCodes::Complete;
	}
	else {
		LastError = GetLastError();
		if (LastError != ERROR_IO_PENDING)
		{
			// Some other error occurred while reading the file.
			CloseHandle(file);
			Status = FileLoaderCodes::ReadError;
		}
		else {
			//Operation has been queued and will complete in the future. 
			Status = FileLoaderCodes::InTransfer;
		}

	}
}

void FileLoader::ReadSynch()
{
	if (ReadFile(file, buffer.data(), Size, &NumberOfBytesTransfered, NULL))
	{
		// Operation has completed.
		CloseHandle(file);
		if (Size == NumberOfBytesTransfered){		//Might be 0 if EOF???
			Status = FileLoaderCodes::Complete;
		}
		else {
			Status = FileLoaderCodes::ReadSizeError;
		}
	}
	else {
		// Some other error occurred while reading the file.
		LastError = GetLastError();
		CloseHandle(file);
		Status = FileLoaderCodes::ReadError;
	}
}

void FileLoader::Tick()
{
	if (Status == FileLoaderCodes::InTransfer)
	{
		if (HasOverlappedIoCompleted(&OverlappedInfo))
		{
			if (GetOverlappedResult(file, &OverlappedInfo, &NumberOfBytesTransfered, false) != 0)
			{
				// Operation has completed.
				CloseHandle(file);
				if (Size == NumberOfBytesTransfered){
					Status = FileLoaderCodes::Complete;
				}
				else {
					Status = FileLoaderCodes::ReadSizeError;
				}
			}
			else{
				// Operation has failed? / HasOverlappedIoCompleted is true
				LastError = GetLastError();
				CloseHandle(file);
				Status = FileLoaderCodes::OverlappedResultError;
			}
		}
	}
}
enum class FileLoaderCodes
{
	Unknown,
	Complete,
	InTransfer,
	InvalidHandle,
	InvalidSize,
	ReadError,
	ReadSizeError,
	AllocError,
	CreateEventError,
	OverlappedResultError
};



#5147726 10-bit Monitors

Posted by Tispe on 17 April 2014 - 02:59 PM

Hello

 

There are new monitors on the market that support 10-bits per channel. But in CAPS I can only find support for D3DFMT_X8R8G8B8 and D3DFMT_R5G6B5.

 

I do not have a 10bit monitor, but if I had one would a 10bit format appear in CAPS?

 

How can DirectX render to 10bit monitors?




#5141126 methods for drawing rain

Posted by Tispe on 21 March 2014 - 04:12 PM


rain falls so fast, the eye can only track it for a split second. so using scrolling or particles to get a "falling" effect are unnecessary. multiple randomly animated textures, or a randomly jittered single texture works just fine.

 

Then why not have a texture atlas of different sized raindrops. And use the ones depending on the viewing angle?




#5138682 Passing Concurreny::concurrent_queue by reference to thread

Posted by Tispe on 13 March 2014 - 07:08 AM

If anyone cares I removed a race condition:

class concurrentIO : public std::enable_shared_from_this<concurrentIO>
{
public:
	shared_ptr<concurrentIO> NoRaceCondition;
	concurrent_queue<string> SendQueue;
	concurrent_queue<string> ReceiveQueue;
};

class Network
{
public:
	Network(void) : Connected(false)
	{
	}
	~Network(void)
	{
		Disconnect();
	}

	void Connect(string server, short port)
	{
		spFIFOs = make_shared<concurrentIO>();
		spFIFOs->NoRaceCondition = spFIFOs;
		thread workerThread = thread(&Network::ThreadRoutine, server, port, spFIFOs.get());
		workerThread.detach();
		Connected = true;
	}
	void Disconnect()
	{
		spFIFOs.reset();
		Connected = false;
	}
	bool Send(string message)
	{
		if(Connected)
		{
			spFIFOs->SendQueue.push(message);
		}

		return Connected;
	}
	bool GetMessage(string &message)
	{
		if(Connected)
		{
			return spFIFOs->ReceiveQueue.try_pop(message);
		}

		return false;
	}

private:
	bool Connected;
	shared_ptr<concurrentIO> spFIFOs;

	static DWORD ThreadRoutine(string server, short port, LPVOID param)
	{
		shared_ptr<concurrentIO> spFIFOs = static_cast<concurrentIO* >(param)->shared_from_this();
		spFIFOs->NoRaceCondition.reset();

		if (enet_initialize () != 0){
			return 1;
		}

		ENetHost* client = NULL;
		client = enet_host_create (NULL, 1, 2, 0, 0);
		if(client == NULL){
			spFIFOs->ReceiveQueue.push(string("An error occurred while trying to create an ENet client host."));
		} else {
			ENetAddress address;
			ENetEvent event;
			ENetPeer *peer = NULL;

			enet_address_set_host(& address, server.c_str());
			address.port = port;

			peer = enet_host_connect(client, & address, 2, 0);    
			if (peer == NULL){
				spFIFOs->ReceiveQueue.push(string("No available peers for initiating an ENet connection."));
			} else {
				if (enet_host_service (client, & event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT){
					spFIFOs->ReceiveQueue.push(string("Connection to server succeeded."));

					bool Quit = false;
					while(!Quit)		
					{
						if(spFIFOs.unique())			//if main side resets its shared pointer to signal Disconnect
						{
							enet_peer_disconnect(peer, 0);
							if(enet_host_service (client, & event, 3000) > 0)
							{
								switch (event.type)
								{
								case ENET_EVENT_TYPE_RECEIVE:
									enet_packet_destroy (event.packet);
									break;
								case ENET_EVENT_TYPE_DISCONNECT:
									spFIFOs->ReceiveQueue.push(string("Disconnection succeeded."));
									continue;
								}
							}
							enet_peer_reset(peer);
							Quit = true;
							continue;
						}

						string SendString;
						while(spFIFOs->SendQueue.try_pop(SendString))
						{
							ENetPacket* packet = enet_packet_create (SendString.c_str(), SendString.length() + 1, ENET_PACKET_FLAG_RELIABLE);
							enet_peer_send(peer, 0, packet);
						}

						if(enet_host_service(client, &event, 0) > 0)
						{
							switch (event.type)
							{
							case ENET_EVENT_TYPE_RECEIVE:
								/*printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
								event.packet -> dataLength,
								event.packet -> data,
								event.peer -> data,
								event.channelID);*/
								spFIFOs->ReceiveQueue.push(string((char*)event.packet->data));
								enet_packet_destroy (event.packet);
								break;
							case ENET_EVENT_TYPE_DISCONNECT:
								spFIFOs->ReceiveQueue.push(string("Disconnected."));
								Quit = true;
							}
						}
					}

				} else {
					enet_peer_reset(peer);
					spFIFOs->ReceiveQueue.push(string("Connection to server failed."));
				}

			}

		}

		spFIFOs->SendQueue.clear();
		if(client) enet_host_destroy(client);
		enet_deinitialize();
		return 0;
	}
};



#5138386 Passing Concurreny::concurrent_queue by reference to thread

Posted by Tispe on 12 March 2014 - 06:56 AM

I think I fixed it.

 

Apperantly, I need to wrap it in std::ref

void Connect(string server, short port)
	{
		workerThread = thread(&Network::ThreadRoutine, server, port, ref(SendQueue), ref(ReceiveQueue));
	}

I have never heard of std::ref before....

 

 

For anyone interested:

class Network
{
public:
	Network(void)
	{
	}
	~Network(void)
	{
		Disconnect();
	}

	void Connect(string server, short port)
	{
		workerThread = thread(&Network::ThreadRoutine, server, port, ref(SendQueue), ref(ReceiveQueue));
		workerThread.detach();
	}
	void Disconnect()
	{
		SendQueue.push(string("..quit"));
	}
	void Send(string message)
	{
		SendQueue.push(message);
	}
	bool GetMessage(string &message)
	{
		return ReceiveQueue.try_pop(message);
	}

private:
	thread workerThread;
	concurrent_queue<string> SendQueue;
	concurrent_queue<string> ReceiveQueue;

	static DWORD ThreadRoutine(string server, short port, concurrent_queue<string> &SendQueue, concurrent_queue<string> &ReceiveQueue)
	{
		if (enet_initialize () != 0){
			return 1;
		}

		ENetHost* client = NULL;
		client = enet_host_create (NULL, 1, 2, 0, 0);
		if(client == NULL){
			ReceiveQueue.push(string("An error occurred while trying to create an ENet client host."));
		} else {
			ENetAddress address;
			ENetEvent event;
			ENetPeer *peer = NULL;

			enet_address_set_host (& address, server.c_str());
			address.port = port;

			peer = enet_host_connect (client, & address, 2, 0);    
			if (peer == NULL){
				ReceiveQueue.push(string("No available peers for initiating an ENet connection."));
			} else {
				if (enet_host_service (client, & event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT){
					ReceiveQueue.push(string("Connection to server succeeded."));
					bool Quit = false;
					while(!Quit)
					{
						string SendString;
						if(SendQueue.try_pop(SendString))
						{
							if(strcmp(SendString.c_str(), "..quit") == 0){
								ReceiveQueue.push(string("Exiting worker thread."));
								Quit = true;
								enet_peer_disconnect(peer, 0);
								if(enet_host_service (client, & event, 3000) > 0)
								{
									switch (event.type)
									{
									case ENET_EVENT_TYPE_RECEIVE:
										enet_packet_destroy (event.packet);
										break;
									case ENET_EVENT_TYPE_DISCONNECT:
										ReceiveQueue.push(string("Disconnection succeeded."));
										continue;
									}
								}

								enet_peer_reset(peer);
								continue;
							} else {
								ENetPacket* packet = enet_packet_create (SendString.c_str(), SendString.length() + 1, ENET_PACKET_FLAG_RELIABLE);
								enet_peer_send (peer, 0, packet);
							}
						}

						if(enet_host_service(client, &event, 1) > 0)
						{
							switch (event.type)
							{
							case ENET_EVENT_TYPE_RECEIVE:
								/*printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
									event.packet -> dataLength,
									event.packet -> data,
									event.peer -> data,
									event.channelID);*/
								ReceiveQueue.push(string((char*)event.packet->data));
								enet_packet_destroy (event.packet);
								break;
							case ENET_EVENT_TYPE_DISCONNECT:
								ReceiveQueue.push(string("Disconnected."));
								Quit = true;
							}
						}
					}

				} else {
					enet_peer_reset (peer);
					ReceiveQueue.push(string("Connection to server failed."));
				}

			}

		}

		SendQueue.clear();
		if(client) enet_host_destroy(client);
		enet_deinitialize();
		return 0;
	}
};




#5138086 Running game Server as a system Service

Posted by Tispe on 11 March 2014 - 06:49 AM

Hi

 

I have a simple server/relay which runs on a Virtual Private Server that I rent for 10$/mo. Sometimes the system may restart abruptly and I have to RDP to the system, and log in in order to start my server application.

 

So I figured that I should rather create a Service, which will run without me having to log in after a system restart.

I am using this tutorial: http://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus

 

Is this an good idea? Any things to keep in mind?

 

 

 

Also, would setting the priority to RealTime work/benefit for a system Service?

SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);



#5132568 Double Dispatch errors

Posted by Tispe on 19 February 2014 - 02:21 AM

Thanks, got it working by moving the class implementation after the declarations.

#define	MsgAddPlayer		1
#define	MsgRmvPlayer		2
#define	MsgPosPlayer		3

struct PlayerData 
{
	DWORD ID;
	float Pos[3];
};

struct MessageBase 
{
	DWORD Type;
	DWORD Size;
};

struct MessageAdd : MessageBase
{
	DWORD ID;
	float Pos[3];
};

struct MessageRemove : MessageBase 
{
	DWORD ID;
};

struct MessagePos : MessageBase 
{
	DWORD ID;
	float Pos[3];
};

struct InstructionBase;
struct InstructionAdd;
struct InstructionRemove;
struct InstructionPos;

class PlayerManager
{
public:
	void Process(InstructionBase& nothing);
	void Process(InstructionAdd& add);
	void Procces(InstructionRemove& remove);
	void Procces(InstructionPos& pos);
//private:
	std::map<DWORD, std::shared_ptr<PlayerData> > PlayersMap;
};

struct InstructionBase 
{
	virtual void Process(PlayerManager& processer){
		processer.Process(*this);
	}
};

struct InstructionAdd : InstructionBase
{
	MessageAdd Data;
	InstructionAdd(DWORD ID, float x, float y, float z)
	{
		Data.Type = MsgAddPlayer;
		Data.ID = ID;
		Data.Pos[0] = x;
		Data.Pos[1] = y;
		Data.Pos[2] = z;
	}
	virtual void Process(PlayerManager& processer){
		processer.Process(*this);
	}
};

struct InstructionRemove : InstructionBase
{
	MessageRemove Data;
	InstructionRemove(DWORD ID)
	{
		Data.Type = MsgRmvPlayer;
		Data.ID = ID;
	}
	virtual void Process(PlayerManager& processer){
		processer.Process(*this);
	}
};

struct InstructionPos : InstructionBase
{
	MessagePos Data;
	InstructionPos(DWORD ID, float x, float y, float z)
	{
		Data.Type = MsgPosPlayer;
		Data.ID = ID;
		Data.Pos[0] = x;
		Data.Pos[1] = y;
		Data.Pos[2] = z;
	}
	virtual void Process(PlayerManager& processer){
		processer.Process(*this);
	}
};

void PlayerManager::Process(InstructionBase& nothing)
{
}

void PlayerManager::Process(InstructionAdd& add)
{
	std::shared_ptr<PlayerData> spNewPlayer(new PlayerData);
	PlayersMap[add.Data.ID] = spNewPlayer;
	spNewPlayer->Pos[0] = add.Data.Pos[0];
	spNewPlayer->Pos[1] = add.Data.Pos[1];
	spNewPlayer->Pos[2] = add.Data.Pos[2];
}

void PlayerManager::Procces(InstructionRemove& remove)
{
	PlayersMap.erase(remove.Data.ID);
}

void PlayerManager::Procces(InstructionPos& pos)
{
	PlayersMap[pos.Data.ID]->Pos[0] = pos.Data.Pos[0];		//x
	PlayersMap[pos.Data.ID]->Pos[1] = pos.Data.Pos[1];		//y
	PlayersMap[pos.Data.ID]->Pos[2] = pos.Data.Pos[2];		//z
}

void GetNewInstructions(std::queue<std::shared_ptr<InstructionBase> > &Instructions)
{
	Instructions.push(std::make_shared<InstructionAdd>(17, 1.0f, 0.0f, 5.0f));
	Instructions.push(std::make_shared<InstructionAdd>(7, 16.0f, 0.0f, 15.0f));
	Instructions.push(std::make_shared<InstructionAdd>(89, -11.0f, 0.0f, 55.0f));
}

//Example
int main(){
	PlayerManager Players;
	std::queue<std::shared_ptr<InstructionBase> > Instructions;

	GetNewInstructions(Instructions);

	while(!Instructions.empty()){
		Instructions.front()->Process(Players);
		Instructions.pop();
	}

	std::cout << Players.PlayersMap[89]->Pos[0] << std::endl;
	std::cout << Players.PlayersMap[89]->Pos[1] << std::endl;
	std::cout << Players.PlayersMap[89]->Pos[2] << std::endl;

	return 0;
}



#5130866 Calling a virtual function, illegal call of non-static member function?

Posted by Tispe on 12 February 2014 - 12:59 PM

In order to completely encapsulate this in a simple class the thread function has to be static. But now the static function can't call a member function.

 

Perhaps this is a viable workaround:

class WorkerThread
{
public:
	WorkerThread(void);
	~WorkerThread(void);

	virtual void ThreadFunction(LPVOID param) = 0;
private:
	HANDLE hThread;
	static DWORD WINAPI ThreadRoutine(LPVOID param);
};
 
WorkerThread::WorkerThread(void)
{
	hThread = CreateThread(NULL, 0, WorkerThread::ThreadRoutine, this, NULL, NULL);
}

DWORD WINAPI WorkerThread::ThreadRoutine(LPVOID param)
{
	static_cast<WorkerThread*>(param)->ThreadFunction(param);
	return 0;
}



#5129561 [DX9] many lights: registers VS Volume Texture

Posted by Tispe on 07 February 2014 - 06:41 AM

I think that the bandwidth usage and overhead of transferring a few kilobytes to the GPU is no problem. You can use Vertex Texture Fetch in the vertex shader to lookup your lights array.

 

Only when you want each light to cast shadows will you notice performance issues.




#5129366 Single tile as background?

Posted by Tispe on 06 February 2014 - 12:33 PM

you set the addressing modes for the sampler, MIRROR or WRAP

device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);

Then you can draw a Quad where the UV addresses goes beyond 1.0f. for example if the vertex has an UV address of 2.0f, you will have the texture repeated two times in the same Quad.






PARTNERS