Lock-free SPMC queue
Memory ordering problem
This line:

        if (first == m_last.load(std::memory_order_relaxed))
            return false;


should be:
        if (first == m_last.load(std::memory_order_acquire))
            return false;

Otherwise, on the next line you may load the wrong value out of m_buffer due to the load being reordered before the load to m_last.  I spotted this because I noticed a memory_order_release without a corresponding memory_order_acquire.  The pop() function also needs a load of m_last with memory_order_acquire.
You have the same problem in push().  If you don't load m_first with memory_order_acquire, you run the risk of writing to the buffer when it is full, thus overwriting some element.  Even the assertion won't help because you could have overwritten the buffer and then loaded a modified value for m_first.
Example of failure
Since your comment indicated that I didn't explain thoroughly enough, I will give an example of how the pop could go wrong.

The queue is empty, with m_first = m_last = 0.
The consumer calls try_pop().
In try_pop(), m_first is loaded as 0.
Now, the cpu speculatively loads m_buffer[0], even though you haven't reached that line yet.
The producer calls push().
The producer writes m_buffer[0], and then increments m_last to 1, in that order.
The consumer reads m_last as 1.
The consumer uses the value speculatively loaded in step 4 as the value for m_buffer[0], but this value is wrong.

By adding the memory_order_acquire, you prevent the load of m_buffer[0] from happening until after step 7.