EntBlog
Code, 3D, Games, Linux and much more...
Compile-Time Strings
April 28, 2009 @ 23:19 | In CodeGems, Programming | 6 Comments |
It would be nice if we had such a feature in the C language, wouldn’t it? The term ‘compile-time string’ is referred here as strings that are converted to unique integer identifiers at compile time. At run-time those identifiers are simple integers that can be compared and hashed very fast. In other languages, like for example Smalltalk, the concept of Symbol implements a similar idea. The following post describes a possible implementation of this feature in C/C++.
Click to read the full article »
Stripping comments from Shader bytecodes
January 15, 2009 @ 21:37 | In CodeGems, Programming | 1 Comment |
In DirectX, when compiling a shader with D3DXCompileShader() a buffer containing the shader bytecodes is received. Apart from the bytecodes, extra content like debug and symbol table information is embedded. That extra information is added in form of comments that probably can be eliminated because you are already processing it at compile-time and it is not needed at run-time when loading the shader.
If you can do without that information the following code will help you to save a few bytes, even halving the size of the byte-code in the best cases.
Although not documented in the DirectX SDK, this CodeGem is not an undocumented hack. The Direct3D shader code format is documented in the MSDN, so it probaly won’t change in future revision of DirectX v9.0 (if there is going to be any more…)
D3DPtr<ID3DXBuffer> StripComments(const D3DPtr<ID3DXBuffer>& code) { // Calculates the new size (without comments) int* codeData = static_cast<int*>(code->GetBufferPointer()); unsigned int sizeInWords = code->GetBufferSize() / 4; unsigned int strippedSizeInWords = sizeInWords; for (unsigned int i = 0; i < sizeInWords; i++) { if ((codeData[i] & 0xffff) == D3DSIO_COMMENT) { int commentSize = codeData[i] >> 16; strippedSizeInWords -= 1 + commentSize; i += commentSize; } } // Creates a new buffer with the original code but omitting the comments D3DPtr<ID3DXBuffer> strippedCode; V(D3DXCreateBuffer(strippedSizeInWords * 4, strippedCode.GetPtrForInit())); int* strippedCodeData = static_cast<int*>(strippedCode->GetBufferPointer()); size_t offset = 0; for (unsigned int i = 0; i < sizeInWords; i++) { if ((codeData[i] & 0xffff) == D3DSIO_COMMENT) { int commentSize = codeData[i] >> 16; i += commentSize; } else { strippedCodeData[offset++] = codeData[i]; } } return strippedCode; }
Capturing OutputDebugString
November 9, 2007 @ 3:20 | In CodeGems, Programming | 1 Comment |
Using OutputDebugString for tracing your programs is probably not a good idea, at least if you have lots of traces being generated (OutputDebugString raises an exception and causes a kernel mode transition). So you will probably end up implementing your own tracing/logging system. Parts of code that are not under your control may be still using OutputDebugString (like Debugging Tools for Windows, DirectX, etc). The code listed below allows capturing OutputDebugString calls generated inside your own process (in fact, it is capturing all the OSD calls generated by all the active processes).
You will need to put this piece of code in a separate thread, but those details are omitted for better clarity.
NOTE: If the process is being debugged, the ODS calls will be intercepted by debugger.
struct DbWinBuffer { DWORD dwProcessId; char data[4096 - sizeof(DWORD)]; }; DbWinBuffer* dbBuffer; HANDLE hAckEvent; HANDLE hEvent; HANDLE hSharedFile; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; ///////////////////////////////////////////////////////////////////////////// sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = true; sa.lpSecurityDescriptor = &sd; if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { printf(”ERROR: InitializeSecurityDescriptor\n”); return 1; } if (!SetSecurityDescriptorDacl(&sd, true, 0, false)) { printf(”ERROR: SetSecurityDescriptorDacl\n”); return 1; } hAckEvent = CreateEvent(&sa, false, false, L”DBWIN_BUFFER_READY”); if (!hAckEvent) { printf(”ERROR: CreateEvent(\”DBWIN_BUFFER_READY\”)\n”); return 1; } hEvent = CreateEvent(&sa, false, false, L”DBWIN_DATA_READY”); if (!hEvent) { printf(”ERROR: CreateEvent(\”DBWIN_DATA_READY\”)\n”); return 1; } hSharedFile = CreateFileMapping((HANDLE)-1, &sa, PAGE_READWRITE, 0, L”DBWIN_BUFFER”); if (!hSharedFile) { printf(”ERROR: CreateFileMapping(\”DBWIN_BUFFER\”)\n”); return 1; } dbBuffer = static_cast<DbWinBuffer*>(MapViewOfFile(hSharedFile, FILE_MAP_READ, 0, 0, 4096)); if (!dbBuffer) { printf(”ERROR: MapViewOfFile\n”); return 1; } SetEvent(hAckEvent); DWORD pid = GetCurrentProcessId(); printf(”Tracing PID: %d\n\n”, pid); for (;;) { DWORD ret = WaitForSingleObject(hEvent, INFINITE); if (ret == WAIT_FAILED) { printf(”ERROR: WaitForSingleObject\n”); return 1; } if (dbBuffer->dwProcessId == pid) { printf(”%s”, dbBuffer->data); } SetEvent(hAckEvent); }
Efficient update of stl containers
May 17, 2006 @ 23:08 | In CodeGems, Programming | 6 Comments |
Update: Fixed some bugs in the sample code.
Update: Note added in the third option about the hint.
I have seen dozens of times code like this to update an entry in a map:
typedef std::map<std::string, int> Items; Items items; Items::iterator it = items.find("counter"); if (it == items.end()) { items.insert(std::make_pair("counter", 1)); } else { it->second++; }
The problem with this code is that you are traversing the map two times if the item is not found in the map, one for the first find and one more for the insert.
You can improve the code with something like this:
std::pair<items::iterator, bool> res = items.insert(std::make_pair("counter", 1)); if(!res.second) { (*res.first).second++; }
This is notably better. You only traverse the map one time. But there is still a problem with this code: you are creating the pair even when you do not need it. In this case the pair is simple and its creation is not a problem, but imagine a pair with more complex objects hard to create. You can avoid the creation with a code like this:
Items::iterator lowerBound = items.lower_bound("counter"); if(lowerBound != items.end() && !(items.key_comp()("counter", lowerBound->first))) { lowerBound->second++; } else { items.insert(lowerBound, std::make_pair("counter", 1)); }
Although being more efficient, this code is more obscure, so in case you do not need those nanoseconds you can live with the more clear second option. Apart from being more obscure, the hint is only that, a hint. The implementation can ignore it. As noted by Steven in the comments below, Visual Studio ignores it for the hash_map and hast_set containers.
Sat, 21 Nov 2009 03:11:10 +0100 / 20 queries. 3.243 seconds / 3 Users Online
|
|
|
|
Theme modified from Pool theme. Valid XHTML and CSS
About
Categories