Importance sampling GGX NDF - fireflies and bright final result
I've made a few changes in my code, so let's start with basic image that I had problem we that we'll state as a problem at the beginning:

After changing part of the code from:
float weight = abs(dot(wo, wm) / (dot(normalTS, wo) * dot(normalTS, wm)));
if (dot(normalTS, wi) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)

To this (i.e. moving part of calculations to world-space):
float weight = abs(dot(wo, wm) / (dot(triangleNormal, incomingRayDirWS) * dot(normalTS, wm)));
if (dot(triangleNormal, rayDirWS) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)

I am getting better results. Here are series of images with different settings:
1024 spp, 4 bounces

5000 spp, 4 bounces

5000 spp, 1 bounce

Notice that 4 bounces version is having more fireflies and noise. Long specular paths might be a reason of introducing noise. Also, 5000 spp are getting darker than 1000 spp. Reason is that path is probably introducing no changes, therefore average color is getting darker. You can see it in the last line of main post. I'm going to put it below for reference:
if (dot(triangleNormal, rayDirWS) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)
    throughput *= F * G * weight;
else
    throughput *= 0;

Last thing. Here is image generated with better method ( https://schuttejoe.github.io/post/ggximportancesamplingpart2/ ). 1024 spp, 4 bounces:


Overall, I got rid of weird noise and artifacts. Algorithm got closer to better method and I think it can be treated as fixed.