It depends on what do you want/expect from your release strategy.
Since you're at peace with using feature branches, it means you're also at peace with potentially complicated branch merges and the risks they bring into your master branch: breakages, delays, etc.
If you have strict release deadlines you'll have a hard time meeting them directly from master, pulling release branches off master after the needed feature branches are merged will give you a chance to stabilize the release codebase by isolating it from changes for future releases which I presume continue to be merged into master. The smaller changes with a lower commit rate should significantly lower the risks compared with the master branch.
Release branches also allow you to provide to your customers release hot fixes and complex release stories: multiple simultaneously supported releases, major/minor/incremental releases, etc. It would be very difficult if not impossible to achieve these while releasing directly from master.
The drawbacks of using release branches:
- your costs will increase as each release branch will require maintenance resources, your teams will have to split focus between the master and release branches (which will diverge), context switching may not be insignificant.
- issues uncovered either on the release branch or on the master branch but also affecting the release branch(es) may have to be separately developed and committed on each of the affected branches (since the branches diverge the fixes may not necessarily be identical in all branch contexts).
If the advantages the release branches offer are of no interest or if their disadvantages are show-stoppers for you and you're fine with an "as-is/take it or leave it" basis for your releases then just use selected master branch refpoints for release candidates and, if they meet your release quality criteria, tag them as releases. If after that any issue is being found with a release - just wait for a subsequent release with the fix (but it may contain other stuff as well).
The major disadvantage of this approach is the difficulty of picking your release candidates in full flow of changes going into master (drinking from the fire hose?). The chances of finding good candidates can be pretty low. What if you don't find any? Attempting to throttle the rate of commits going into master in an effort to stabilize it prior to a release will translate into delayed integration (features staying in their dev branch silos longer than absolutely needed), increasingly complicated branch merges, which will eventually cause compounding delays/slips in all your future releases.
Up to you to chose the lesser evil. This is why I'm a fan of continuous integration - at least the complicated merges are out of the picture. The release strategy considerations still apply with CI - the release strategy kicks in after the integration is done - but the 2 evils are "less bad" :) From my experience significantly less. And with a gating CI system in place it's possible to keep master stable regardless of the commit rate.