<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.6.2">Jekyll</generator><link href="http://www.devans.xyz/feed.xml" rel="self" type="application/atom+xml" /><link href="http://www.devans.xyz/" rel="alternate" type="text/html" /><updated>2017-10-24T00:45:02+00:00</updated><id>http://www.devans.xyz/</id><title type="html">Daniel Evans</title><subtitle>C++ and Graphics, mostly
</subtitle><entry><title type="html">Improving OpenGL Performance</title><link href="http://www.devans.xyz/2017/10/08/improving-opengl-performance.html" rel="alternate" type="text/html" title="Improving OpenGL Performance" /><published>2017-10-08T00:00:00+00:00</published><updated>2017-10-08T00:00:00+00:00</updated><id>http://www.devans.xyz/2017/10/08/improving-opengl-performance</id><content type="html" xml:base="http://www.devans.xyz/2017/10/08/improving-opengl-performance.html">&lt;p&gt;The in game performance of &lt;a href=&quot;https://github.com/rwengine/openrw&quot;&gt;OpenRW&lt;/a&gt; was worse
than it should be. I investigated why and made great performance improvements on
an important platform: laptop GPUs. This post covers the investgation and the
changes made.&lt;/p&gt;

&lt;h2 id=&quot;testing-performance&quot;&gt;Testing Performance&lt;/h2&gt;

&lt;p&gt;OpenRW has a “test mode” that spawns several vehicles and pick-ups in a central
location. Performance in this spot isn’t great, so I started there. I took samples
from two angles, looking at the horizon and looking at the ground. There was quite
a difference in performance between the two situations.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;View&lt;/th&gt;
      &lt;th&gt;Frame time&lt;/th&gt;
      &lt;th&gt;Draws&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Ground&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;7.3 ms&lt;/td&gt;
      &lt;td&gt;191&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Horizon&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;17.7 ms&lt;/td&gt;
      &lt;td&gt;1035&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;cpu-profiling-with-perf&quot;&gt;CPU Profiling with Perf&lt;/h2&gt;

&lt;p&gt;To try and understand what is happening I began profiling with &lt;a href=&quot;https://perf.wiki.kernel.org/index.php/Main_Page&quot;&gt;perf&lt;/a&gt;.
I ran perf in the following way, which spawns &lt;code class=&quot;highlighter-rouge&quot;&gt;sleep&lt;/code&gt; but records samples from
rwgame (the process name for OpenRW), an easy way to record for a fixed length of time.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ perf record -p $(pidof rwgame) sleep 15
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the process exits, &lt;code class=&quot;highlighter-rouge&quot;&gt;perf record&lt;/code&gt; writes out a file containing the samples it took.
The data can be viewed in the terminal by running &lt;code class=&quot;highlighter-rouge&quot;&gt;perf report&lt;/code&gt;. I recorded a
few sessions looking at the horizon, and the report was roughly the same each time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/perf_CPU.png&quot; alt=&quot;Perf Report Output&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The top two most sampled methods are within the Intel GPU driver, followed by
bullet (I’m not sure what causes the odd symbol names like &lt;code class=&quot;highlighter-rouge&quot;&gt;0x0000000000007e45&lt;/code&gt;).
It is clear that a lot of time is spent in the driver, more than I would expect
for such a simple scene.&lt;/p&gt;

&lt;p&gt;Since the CPU profile shows a lot of time in the driver, I suspected that the
OpenGL usage was far from optimal. To see what was happening between OpenRW and
the driver, I needed to take a look at the GL calls. There’s some good tools for
this these days: &lt;a href=&quot;https://renderdoc.org/&quot;&gt;RenderDoc&lt;/a&gt; and &lt;a href=&quot;https://apitrace.github.io/&quot;&gt;apitrace&lt;/a&gt;
being the most portable.&lt;/p&gt;

&lt;h2 id=&quot;opengl-debugging-with-apitrace&quot;&gt;OpenGL debugging with apitrace&lt;/h2&gt;

&lt;p&gt;OpenRW doesn’t do anything complicated so using apitrace to inspect the raw OpenGL
calls is easy enough. I captured a trace of the &lt;em&gt;Horizon&lt;/em&gt; scene like so:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ apitrace trace -o test_mode.trace ./rwgame/rwgame -t
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The trace can be viewed with the GUI trace viewer QApitrace, or inspected with
command line tools.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/qapitrace_before.png&quot; alt=&quot;QApitrace showing repeated calls to glEnable(GL_BLEND)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This trace shows a couple of issues:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Enable(GL_BLEND)&lt;/code&gt; is called repeatedly to no effect: a bug.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;BufferData&lt;/code&gt; is called for each draw to upload data: expensive.&lt;/li&gt;
  &lt;li&gt;Each draw requires a new VAO be bound: expensive&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;state-caching&quot;&gt;State Caching&lt;/h3&gt;
&lt;p&gt;Calling &lt;code class=&quot;highlighter-rouge&quot;&gt;Enable(GL_BLEND)&lt;/code&gt; repeatedly isn’t going to do us any favours,
and could be obscuring some bugs elsewhere. This is the first thing I decided to
fix as it shouldn’t have been happening in the first place. The rendering system
is intended to cache the set state and only change it if we have to, but the
method responsible, &lt;code class=&quot;highlighter-rouge&quot;&gt;OpenGLRenderer::setBlend(bool)&lt;/code&gt; didn’t even check if we
were trying to turn it on, it just called &lt;code class=&quot;highlighter-rouge&quot;&gt;glEnable(GL_BLEND)&lt;/code&gt; no matter what.
I corrected that and immediatley a few things broke:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/not_blended.png&quot; alt=&quot;Transparent elements not rendering correctly&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The issue was just down to the map and particle system not enabling the blending
state, even though they relied on it. This was overlooked previously because 
the bug in &lt;code class=&quot;highlighter-rouge&quot;&gt;setBlend&lt;/code&gt; left the state enabled. After updating those call sites
to set the correct state, &lt;a href=&quot;https://github.com/danhedron/openrw/commit/7f2c512f50ea6bd4e08e7d85e58f770ac4af8d26&quot;&gt;it was fixed&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;buffer-updates&quot;&gt;Buffer Updates&lt;/h3&gt;

&lt;p&gt;The next issue on the list is the per-draw data updates. Calling &lt;code class=&quot;highlighter-rouge&quot;&gt;BufferData&lt;/code&gt;
for each draw is expensive. I consulted the “&lt;a href=&quot;http://gdcvault.com/play/1020791/&quot;&gt;Approaching Zero Driver Overhead&lt;/a&gt;”
presentation for guidance, and decided to implement a simple solution:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Determine the largest UBO size available from the driver.&lt;/li&gt;
  &lt;li&gt;Decide how many draw calls worth of data can fit inside a single UBO.&lt;/li&gt;
  &lt;li&gt;Then, Per-Draw:
    &lt;ol&gt;
      &lt;li&gt;If we have run out of space in our UBO, reset the counter and get new storage with &lt;code class=&quot;highlighter-rouge&quot;&gt;BufferData&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;use &lt;code class=&quot;highlighter-rouge&quot;&gt;MapBuffer&lt;/code&gt; with the offset for our current draw data, copy the data into the buffer and unmap.&lt;/li&gt;
      &lt;li&gt;Bind the UBO at the offset for the current draw, and Draw.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn’t as extreme as using persistent mapping like the AZDO presentation
suggests, but should at least avoid some of the pressure of re-allocating storage
for each draw that the driver is still trying to use. It also has the benefit
of not requiring OpenGL 4.0, unlike persistent mapping.&lt;/p&gt;

&lt;p&gt;The result is a significant increase in performance, slicing several milliseconds
off most frames. Revisiting the original test shows what impact the buffer update
strategy has, a pretty reasonable 30% improvement.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;View&lt;/th&gt;
      &lt;th&gt;Frame time&lt;/th&gt;
      &lt;th&gt;Draws&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Ground&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;6.7 ms&lt;/td&gt;
      &lt;td&gt;250&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Horizon&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;12.2 ms&lt;/td&gt;
      &lt;td&gt;1063&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;While 30% is a modest improvement in performance, there is more that can be gained
by applying some further changes to how rendering works:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Allocating one buffer for multiple vertex and index data, to reduce buffer changes.&lt;/li&gt;
  &lt;li&gt;Copying draw data to buffers in larger batches.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But these can wait. Performance has improved enough already to make OpenRW playable
so it is more important to fix gameplay issues and make sure it’s actually worth playing.&lt;/p&gt;</content><author><name></name></author><summary type="html">The in game performance of OpenRW was worse than it should be. I investigated why and made great performance improvements on an important platform: laptop GPUs. This post covers the investgation and the changes made.</summary></entry><entry><title type="html">Texture Containers</title><link href="http://www.devans.xyz/2017/04/04/texture-containers.html" rel="alternate" type="text/html" title="Texture Containers" /><published>2017-04-04T00:00:00+00:00</published><updated>2017-04-04T00:00:00+00:00</updated><id>http://www.devans.xyz/2017/04/04/texture-containers</id><content type="html" xml:base="http://www.devans.xyz/2017/04/04/texture-containers.html">&lt;h1 id=&quot;textures-filtering-and-mipmaps&quot;&gt;Textures, Filtering and Mipmaps&lt;/h1&gt;

&lt;p&gt;When writing simple applications using OpenGL, it’s not uncommon to use a library
such as &lt;a href=&quot;https://github.com/nothings/stb/blob/master/stb_image.h&quot;&gt;stb_image&lt;/a&gt; or
&lt;a href=&quot;http://www.lonesock.net/soil.html&quot;&gt;SOIL&lt;/a&gt; to load a PNG or JPEG image as a texture.
This is nice and convenient. The ease of use doesn’t come with downsides, however.
The compression used for JPEG and PNG leaves the image in a format unsuitable for
the random-access required by texture sampling on the GPU. To make these images
usable, they are decompressed before being uploaded. The decompression step, while
quick, can add up if you have a large number of textures or a very tight budget.
For example if you are streaming data in-game, naïvely decompressing many JPGs
or PNGs will eat into your 16.6ms budget.&lt;/p&gt;

&lt;p&gt;Unless you are rendering a screen-sized texture onto a screen-sized quad, each
pixel in the image is unlikely to cover 1 pixel on the screen. To improve the
quality of the texture when viewed smaller, larger, and at shallow angles,
filtering techniques are used to get a plausible colour for each sample. Mipmaps
are the most important for this post.&lt;/p&gt;

&lt;p&gt;The idea behind mipmaps is that rather than have a single screen pixel cover 10s
or more texture pixels, a smaller version of the texture is used that has better
coverage, requiring fewer samples. Thus each texture is not an individual image,
but a series of mipmap levels, each half the size of the previous level. To give
an example, a texture that’s 256x256 pixels, could have mipmaps for 128x128,
64x64, 32x32, and so on. If the view was facing directly at a plane with this
texture (let’s say it’s a brick wall), then depending on the distance
and viewport size moving away from the wall would select progressively smaller
mipmaps for use to keep the ratio of texture pixels to screen pixels reasonable.&lt;/p&gt;

&lt;p&gt;Usual image formats don’t support storing these mipmap chains. When loading a
JPG or a PNG, mipmaps must be generated by resizing the original image repeatedly
for each required mipmap level. That’s no problem if you only have 10 textures,
but if you have 100s of textures or need to stream in textures at run-time, then
spending time generating these smaller images will be something worth reducing.&lt;/p&gt;

&lt;p&gt;Texture containers are a solution to these problems. Not only do they store texture
data suitable for direct use as textures, they also store mip-map and array data.
This means a single texture container can store all the data required for an entire
texture, no matter it’s size, number of mipmaps, array layers or cubemap faces.
Generating mipmaps offline is important if you use compressed textures, as it’s
generally impractical to generate compressed textures at runtime.&lt;/p&gt;

&lt;h1 id=&quot;container-formats&quot;&gt;Container formats&lt;/h1&gt;

&lt;p&gt;The most common texture container formats in use that store data compatible with
D3D, OpenGL or Vulkan, are the Khronos Texture format (KTX) and DirectDraw Surface
(DDS).&lt;/p&gt;

&lt;h2 id=&quot;khronos-texture-ktx&quot;&gt;Khronos Texture (KTX)&lt;/h2&gt;
&lt;p&gt;Khronos Texture is a Khronos Group standard for storing textures intended for
use with OpenGL and OpenGL ES. The specification for the format is available via
&lt;a href=&quot;https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/&quot;&gt;Khronos&lt;/a&gt;.
It contains format information directly compatible with OpenGL and OpenGL ES
enumerations. Also included is the ability to store application specific key-value
data within the file.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/&quot;&gt;specification&lt;/a&gt;
provides a good overview of the format and the expected values for each of the
header fields. The format can store 1D, 2D, 3D, Cubemaps and Array Textures, along
with any number of mipmaps for these textures. This makes it ideal for storing
almost any kind of texture you could want.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/KTX_format.png&quot; alt=&quot;KTX Format Structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The texture data is described in the&lt;code class=&quot;highlighter-rouge&quot;&gt;glType&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;glFormat&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;glInternalFormat&lt;/code&gt;,
and &lt;code class=&quot;highlighter-rouge&quot;&gt;glBaseInternalFormat&lt;/code&gt; header fields. These should match up with the parameters
to the &lt;code class=&quot;highlighter-rouge&quot;&gt;gl[Compressed]Tex[Sub]Image*D&lt;/code&gt; calls used to submit each texture mipmap level’s data.&lt;/p&gt;

&lt;h2 id=&quot;directdraw-surface-dds&quot;&gt;DirectDraw Surface (DDS)&lt;/h2&gt;
&lt;p&gt;Despite DirectDraw being long deprecated, the DDS format is still in common use
for storing textures used with Direct3D. Originally only 2D textures were supported,
but the D3D10 header extension added support for texture arrays and D3D10+ features.
The format is partially documented along with expected values on &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/bb943991(v=vs.85).aspx&quot;&gt;MSDN&lt;/a&gt;,
useful for integrating DDS into your pipeline.&lt;/p&gt;

&lt;p&gt;For loading DDS in D3D11, there is a deprecated function, &lt;code class=&quot;highlighter-rouge&quot;&gt;D3DX11CreateTextureFromFile&lt;/code&gt;,
which is no longer available in Windows Store apps. &lt;a href=&quot;https://github.com/Microsoft/DirectXTK&quot;&gt;DirectXTK&lt;/a&gt; has a replacement, &lt;a href=&quot;https://github.com/Microsoft/DirectXTK/wiki/DDSTextureLoader&quot;&gt;DDSTextureLoader&lt;/a&gt; that can be used instead.&lt;/p&gt;

&lt;h1 id=&quot;use-containers&quot;&gt;Use containers&lt;/h1&gt;

&lt;p&gt;Since KTX is somewhat better specified that DDS, I would recommend using it over DDS.
Howerver, as long as you use a sensible format that simplifies storing and loading,
you should benefit from the increased simplicity and reduced loading times.
There is an official KTX library &lt;a href=&quot;https://github.com/KhronosGroup/KTX&quot;&gt;libktx&lt;/a&gt; for
working with KTX files. More information about this is available on the &lt;a href=&quot;https://www.khronos.org/opengles/sdk/tools/KTX/&quot;&gt;Khronos website&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html">Textures, Filtering and Mipmaps</summary></entry><entry><title type="html">clang-format</title><link href="http://www.devans.xyz/2017/02/22/clang-format.html" rel="alternate" type="text/html" title="clang-format" /><published>2017-02-22T00:00:00+00:00</published><updated>2017-02-22T00:00:00+00:00</updated><id>http://www.devans.xyz/2017/02/22/clang-format</id><content type="html" xml:base="http://www.devans.xyz/2017/02/22/clang-format.html">&lt;p&gt;Reducing the effort required to keep code style consistent is important, because
doing so helps readability, and the task is not very interesting.
&lt;a href=&quot;https://clang.llvm.org/docs/ClangFormat.html&quot;&gt;clang-format&lt;/a&gt; is a great tool for
re-styling entire C++ files, or even small sections, automatically.
It provides a wide array of configuration options, &lt;a href=&quot;https://clang.llvm.org/docs/ClangFormatStyleOptions.html&quot;&gt;listed here&lt;/a&gt;, and some default configurations for style guides
from LLVM, Google, etc.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/rwengine/openrw&quot;&gt;OpenRW&lt;/a&gt; project provides a clang-format
configuration that applies a reasonable style to the codebase. While using it
I’ve found a few useful things that improve my workflow, and have some ideas of
what could be improved.&lt;/p&gt;

&lt;h2 id=&quot;trailing-comma-in-list-initialisation&quot;&gt;Trailing comma in list initialisation&lt;/h2&gt;
&lt;p&gt;Leaving a trailing comma in a C++ list initialisation is a useful pattern for lists
that are likely to change. As you don’t need to change the previous entry if you
add another element.&lt;/p&gt;

&lt;p&gt;clang-format takes this &lt;a href=&quot;http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20140317/101748.html&quot;&gt;into account&lt;/a&gt;
by breaking each element onto its own line if there is a trailing comma after
the last item. This greatly improves readability in larger lists and simplifies
diffs when changes are made.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mytype_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kMyElements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;baz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;three&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The 2nd element has been squashed down to one line, despite being almost exactly
the same number of symbols as the first. This is great for nested structures
and long lists that are difficult to read when not expanded.&lt;/p&gt;

&lt;h2 id=&quot;qtcreator-integration&quot;&gt;QtCreator integration&lt;/h2&gt;
&lt;p&gt;QtCreator is my daily driver, and so it would be useful to have a hotkey for
applying clang-format to a block of code. The QtCreator developers seem to feel
the same way, since it comes with a plugin called Beautifier. This can apply
a few different code styling tools to open documents, including clang-format.&lt;/p&gt;

&lt;p&gt;To enable it, just click &lt;code class=&quot;highlighter-rouge&quot;&gt;Help&lt;/code&gt; &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;About Plugins&lt;/code&gt; and tick Beautifier, then
restart QtCreator. You can then run clang-format from the &lt;code class=&quot;highlighter-rouge&quot;&gt;Tools&lt;/code&gt; menu.
Unfortunatley you can’t select a clang format configuration file to use, but you
can copy the configuration into the &lt;code class=&quot;highlighter-rouge&quot;&gt;Tools&lt;/code&gt; &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Options&lt;/code&gt; &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Beautifier&lt;/code&gt; &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;clang-format&lt;/code&gt; screen.&lt;/p&gt;

&lt;p&gt;I find it’s useful to have a keyboard shortcut to continually re-format the code
I’m working on. To set up a hotkey for this, click on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Environment&lt;/code&gt; &amp;gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;Keyboard&lt;/code&gt; tab, then search for clangformat. I typically use &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl+?&lt;/code&gt;
as it doesn’t conflict with anything else.&lt;/p&gt;

&lt;h2 id=&quot;enforcing-style-in-pull-requests&quot;&gt;Enforcing style in pull requests&lt;/h2&gt;
&lt;p&gt;As the number of contributors to OpenRW increases, reducing the burden on those
reviewing pull requests is critical. Nit picking about style is something nobody
should expend effort over, so I would like to have clang-format be part of the
continious integration process.&lt;/p&gt;

&lt;p&gt;I’e not yet implemented this in the OpenRW project but I can imagine a system
that I would be reasonable to use. Before the code is built on travis, a
script should run that applies clang-format to the lines changed between the master
and the branch commits. If this script produces any output, then the build will
be marked as failed and the user should get a useful diagnostic of what they need
to change to fix the style.&lt;/p&gt;</content><author><name></name></author><summary type="html">Reducing the effort required to keep code style consistent is important, because doing so helps readability, and the task is not very interesting. clang-format is a great tool for re-styling entire C++ files, or even small sections, automatically. It provides a wide array of configuration options, listed here, and some default configurations for style guides from LLVM, Google, etc.</summary></entry></feed>