All Blog Entries

All blog entries, ordered from most recent. Entry count: 1071.

Pages: > 1 2 3 4 ... 134 >

# Ported CommonLib to 64 Bits

22:12
Sun
12
Nov 2017

I recently updated my CommonLib library to support 64-bit code. This is a change that I planned for a very long time. I written this code so many years ago that 64-bit compilation on Windows was not popular back then. Today we have opposite situation - a modern Windows application or game could be 64-bit only. I decided to make the library working in both configurations. The way I did it was:

  1. Created 64-bit configurations in Visual Studio project.
  2. Went over all the code. Made changes required to work correctly in 64-bit configuration.
  3. Compiled the code - made sure it's compiling successfully.
  4. Fixed everything that compiler reported as warnings.
  5. Made sure tests are passing.
  6. Scanned the code with PVS-Studio static code analysis tool. I covered this point in a separate blog post.

The most important and also most frequent change I needed to make in the code was to use size_t type for every size (like the number of bytes), index (for indexing arrays), count (number of elements in some collection), length (e.g. number of characters in a string) etc. This is the "native" type intended for that purpose and as such it's 32-bit or 64-bit, depending on configuration. This is also the type returned by sizeof operator and functions like strlen. Before making this change, I carelessly mixed size_t with uint32.

I sometimes use maximum available value (all ones) as a special value, e.g. to communicate "not found". Before the change I used UINT_MAX constant for that. Now I use SIZE_MAX.

I know there is a group of developers who advocate for using signed integers for indices and counts, but I'm among the proponents of unsigned types, just like C++ standard recommends. In those very rare situations where I need a signed size, correct solution is to use ptrdiff_t type. This is the case where I apply the concept of "stride", which I blogged about here (Polish) and here.

I have a hierarchy of "Stream" classes that represent a stream of bytes that can be read from or written to. Derived classes offer unified interface for a buffer in memory, a file and many other. Before the change, all the offsets and sizes in my streams were 32-bit. I needed to make a decision how to change them. My first idea was to use size_t. It seems natural choice for MemoryStream, but it doesn't make sense for FileStream, as files can always exceed 4 GB size, regardless of 32/64-bit configuration of my code. Such files were not supported correctly by this class. I eventually decided to always use 64-bit types for stream size and cursor position.

There are cases where my usage of size_t in the library interface can't work down to the implementation, because underlying API supports only 32-bit sizes. That's the case with zlib (a data compression library that I wrapped into stream classes in files ZlibUtils.*), as well as BSTR (string type used by Windows COM that I wrapped into a class in files BstrString.*). In those cases I just put asserts in the code checking whether actual size doesn't exceed 32-bit maximum before downcasting. I know it's not the safe solution - I should report error there (throw an exception), but well... That's only my personal code anyway :)

BstrString::BstrString(const wchar_t *wcs, size_t wcsLen)
{
    (...)
    assert(wcsLen < (size_t)UINT_MAX);
    Bstr = SysAllocStringLen(wcs, (UINT)wcsLen);

From other issues with 64-bit compatibility, the only one was following macro:

/// Assert that ALWAYS breaks the program when false (in debugger - hits a breakpoint, without debugger - crashes the program).
#define	ASSERT_INT3(x) if ((x) == 0) { __asm { int 3 } }

The problem is that Visual Studio offers inline assembler in 32-bit code only. I needed to use __debugbreak intrinsic function from intrin.h header instead.

Overall porting of this library went quite fast and smoothly, without any major issues. Now I just need to port the rest of my code to 64 bits.

Comments | #visual studio #c++ #commonlib Share

# New Version of PVS-Studio

21:11
Thu
09
Nov 2017

PVS-Studio is a great, commercial static code analyzer. I blogged about it few years ago. Now the latest version is much more powerful. It supports C, C++, and C#, works on Windows and Linux, as a standalone app, as well as plugin for Visual Studio (including latest version 2017).

PVS-Studio is particularly good at finding issues with code portability between 32-bit and 64-bit. Out of my personal projects, I already ported CommonLib to 64 bits, and RegScript2 is written to support 64 bits from the start, but porting my main app (music visualization program) to 64 bits is a large task that I still have on my TODO list. Even if I know how to write portable code (use size_t not int etc. :) I made first commits to this repository 8 years ago, when my programming knowledge was much smaller, so I'm sure there are many nasty bugs there. Making it working as 64-bit app will be a difficult task and I'm sure PVS-Studio will help me with that. I will share my experiences and conclusions when I eventually do it.

In the meantime, I recommend to check their Blog, where developers of this tool share many valuable information. They also maintain list of articles describing errors they found in open source projects.

Comments | #tools #c++ #pvs-studio #visual studio Share

# Immediate Mode GUI - Theory and Example - Slides

21:06
Tue
24
Oct 2017

Today I gave a talk at Warsaw GameDev Meetup. Topic of my presentation was: "Immediate Mode GUI - Theory and Example". You can download slides here:

Comments | #gui #teaching #events Share

# Lost clicks and key presses on low FPS

13:34
Sun
22
Oct 2017

There is a problem with handling input from mouse and keyboard in games and other interactive applications that I just solved. I would like to share my code for the solution. When your app uses a loop that constantly calculates and renders frames, like games usually do, it may seem natural to just read current state of every mouse and keyboard key (whether it's down or up) on each frame. You may then caculate derived information, like whether a button has just been pressed on released, by comparing new state to the state from previous frame. This is how Dear ImGui library works. So first solution could look like this:

void UpdateFrame()
{
    // Fill ImGui::GetIO().DeltaTime, KeyCtrl, KeyShift, KeyAlt etc.
    ImGui::GetIO().MouseDown[0] = (GetKeyState(VK_LBUTTON) & 0x8000) != 0;
    ImGui::GetIO().MouseDown[1] = (GetKeyState(VK_RBUTTON) & 0x8000) != 0;
    ImGui::GetIO().MouseDown[2] = (GetKeyState(VK_MBUTTON) & 0x8000) != 0;
    for(uint32_t i = 0; i < 512; ++i)
        ImGui::GetIO().KeysDown[i] = (GetKeyState(i) & 0x8000) != 0;
    
    ImGui::NewFrame();
    
    if(ImGui::IsKeyPressed('A'))
        // Do something...
}

There is one problem with this approach. If user presses and releases a key for a very short time, so that both press and release happens between two frame, it will go unnoticed. This is very annoying. It happens especially when:

First step towards solving this is to react to "real" events that are sent by the operating system:

Read full entry > | Comments | #gui #winapi #windows Share

# VK_KHR_dedicated_allocation unofficial manual

22:36
Mon
16
Oct 2017

I wrote a short article that explains how to use Vulkan extenion "VK_KHR_dedicated_allocation". It may be interesting to you if you are a programmer and you code graphics using Vulkan.

Go to article: VK_KHR_dedicated_allocation unofficial manual

Comments | #graphics #vulkan Share

# How to check if an integer number is a power of 10?

23:30
Wed
04
Oct 2017

I was recently asked a test question to write a function that would check whether a given integer number is a power of ten. I didn't know the answer immediately because I never solved this puzzle before, so I needed to think about a solution. I quickly came to a conclusion that there are many possible solutions, so I later decided to write them down and share with you.

Number is a power of 10 if it's equal to 10, 100, 1000 etc. 1 is also 0-th power of 10. Other numbers like 2, 3, 11, 12 etc. are not powers of 10. 0 and all negative numbers should also be rejected.

Below you can find 5 different solutions - all of them correct, but some of them more efficient than others. Example code is in C, but you can easily implement the same algorithms in Java or any other programming language.

First thing that came to my mind was to convert the number to a string and check whether it contains '1' followed by '0'-s.

int IsLog10_v1(int32_t x)
{
// Convert x to string.
char buf[12];
itoa(x, buf, 10);
const size_t bufLen = strlen(buf);

// Check if string contains '1' followed by '0'-s.
if(buf[0] != '1')
return 0;
for(size_t i = 1; i < bufLen; ++i)
{
if(buf[i] != '0')
return 0;
}
return 1;
}

Another option is to convert the number to floating-point format, use "real" log10 function, and check if the result is an integer. Note that double must be used here, because float has too small precision and would incorrectly return 1 for inputs like: 999999999, 1000000001.

int IsLog10_v2(int32_t x)
{
// Convert x to double. Calculate log10 of it.
double x_d = (double)x;
double x_log10 = log10(x_d);
// Check if result is integer number - has zero fractional part.
return x_log10 - floor(x_log10) == 0.0;
}

If we want to operate on integer numbers only, we may come up with a recursive algorithm that checks whether the number is greater than zero, divisible by 10 and then calls the same function for x/10.

int IsLog10_v3(int32_t x)
{
if(x <= 0)
return 0;
if(x == 1)
return 1;
if(x % 10 != 0)
return 0;
// Recursion.
return IsLog10_v3(x / 10);
}

Because it's a tail recursion, it's easy to convert it to iterative algorithm (use loop instead of recursive call).

int IsLog10_v4(int32_t x)
{
if(x <= 0)
return 0;
// Same algorithm as v3, but converted from recursion to loop.
for(;;)
{
if(x == 1)
return 1;
if(x % 10 != 0)
return 0;
x /= 10;
}
}

Finally, the most efficient solution is to notice that there are only few possible powers of 10 in the range of 32-bit integers, so we can just enumerate them all.

int IsLog10_v5(int32_t x)
{
// Just enumerate all possible results.
return
x == 1 ||
x == 10 ||
x == 100 ||
x == 1000 ||
x == 10000 ||
x == 100000 ||
x == 1000000 ||
x == 10000000 ||
x == 100000000 ||
x == 1000000000;
}

You can find full source code as a simple, complete C program together with tests on my GitHub, as file: IsLog10.c.

Comments | #c #algorithms Share

# Vulkan Memory Allocator 2.0.0-alpha.3

13:42
Wed
13
Sep 2017

I just published new version of Vulkan Memory Allocator 2.0.0-alpha.3. I'm quite happy with the quality of this code. Documentation is also updated, so if nothing else, please just go see User guide. I still marked it as "alpha" because I would like to ask for feedback and I may still change everything.

I would like to discuss proposed terminology. Naming things in code is a hard problem in general, and especially as English is not my native language, so please fill free to contact me and propose more elegant names to what I called: allocator, allocation, pool, block, stats, free range, used/unused bytes, own memory, persistently mapped memory, pointer to mapped data, lost allocation (becoming lost, making other lost), defragmentation, and used internally: suballocation, block vector.

Comments | #vulkan #productions #libraries #graphics Share

# What is Samsung phone doing to photos?! (sharpening a lot)

23:15
Mon
11
Sep 2017

I now use Samsung Galaxy S7 smartphone and I'm quite happy with it, except for the camera. I noticed that all the photos taken with it look bad. There is clearly something wrong with them. When I zoomed in, I noticed that the device applies insane amount of sharpening. Every photo looks like it was first filtered by bilateral filter (a kind of edge-preserving blur that is used for noise reduction) and then sharpening with intensity set to maximum, which causes annoying ringing artifacts around the edges.

I decided to make an experiment. I gathered all the devices I had access to that can take photos and I brought them to a place where I could photograph a building that has many sharp edges, plus some tram cables. It was the middle of a sunny day, so lighting brightness and contrast was high and devices didn't have a reason to apply too much processing to the photos taken. I configured all of them to fully automatic mode, maximum resolution and JPEG as output format (except Canon camera, where I forgot about it, so I actually made CR2 RAW that I later converted to JPEG). Devices I used for comparison were (click on each link to access original photo file):

When you zoom in to the building, you can clearly see that both Samsung phones applied very strong sharpening. It turns out this is a known problem. There is a discussion on Reddit, as well as YouTube video about it. Sony phone and DSLR don't have this effect.

Samsung Galaxy S6:

Samsung Galaxy S7:

Sony Xperia Z2:

Canon PowerShot G7X Mark II:

Nikon D90:

What's interesting is that the Canon camera also applied some sharpening, and did it even in RAW! (How can they call it RAW then?!) Fortunately in this camera it can be disabled: While in photo shooting mode, press MENU button, go to tab 6, select "Picture Style" and set it to "Neutral", so that the first parameter in the sequence of numbers (meaning "Sharpness Strength") is 0.

In Samsung phones this filter cannot be disabled :( The only way to take pictures without it is to use RAW, where it's not applied. To do it, while in photo shooting mode: swipe left, choose "Professional", enter configuration, select "Image size" and there enable "Save RAW and JPEG files". You need to enter "Professional" mode every time you want to take a photo. Then of course you need to process the image on your PC and convert it to JPEG, e.g. in Adobe Lightroom or other similar program, but there you can decide how much sharpening do you need (or none).

Comments | #photography #hardware Share

Pages: > 1 2 3 4 ... 134 >

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror]
Copyright © 2004-2018