<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Match3 on Jendrik Illner - 3D Programmer</title>
    <link>https://www.jendrikillner.com/tags/match3/</link>
    <description>Recent content in Match3 on Jendrik Illner - 3D Programmer</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>&amp;copy; 2023 · Jendrik Illner</copyright>
    <lastBuildDate>Thu, 12 Nov 2020 04:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://www.jendrikillner.com/tags/match3/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Rust Game Series - Part 15 - Texture Pipeline and Pixel Perfect Rendering</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-15/</link>
      <pubDate>Thu, 12 Nov 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-15/</guid>
      <description>

&lt;p&gt;In the last part of this series, I have discussed the DDS loader implementation. Now it&amp;rsquo;s time to build on this and actually start drawing some textures onto the screen.&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;In this part, I am going to discuss the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asset pipeline setup&lt;/li&gt;
&lt;li&gt;Texture loading integration&lt;/li&gt;
&lt;li&gt;Debugging advice for Pixel-Perfect rendering&lt;/li&gt;
&lt;li&gt;Game screen drawing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All assets for this game are from the &lt;a href=&#34;https://monixxy.itch.io/kawaii-cookie-match-3-asset-pack&#34; target=&#34;_blank&#34;&gt;kawaii cookie match 3 asset pack&lt;/a&gt;.
I am very thankful that the author has given me permission to include parts of this art pack for the series.&lt;/p&gt;

&lt;h2 id=&#34;texture-pipeline&#34;&gt;Texture Pipeline&lt;/h2&gt;

&lt;p&gt;The Asset pack provides the source data SVGs, and the game will need to load them as DDS files.&lt;/p&gt;

&lt;p&gt;The conversion could be done manually but I always want all my assets to be stored in source format and fully automate the pipeline of making the data game ready.&lt;/p&gt;

&lt;p&gt;The Git repository only contains the game ready data and not the source data.
The pipeline is fully included in GIT so the asset pack can be used as-is.&lt;/p&gt;

&lt;h3 id=&#34;pipeline-architecture&#34;&gt;Pipeline Architecture&lt;/h3&gt;

&lt;p&gt;For my asset pipeline setup, I am using &lt;a href=&#34;https://ninja-build.org&#34; target=&#34;_blank&#34;&gt;Ninja&lt;/a&gt;.
It&amp;rsquo;s my favorite build system. It&amp;rsquo;s small, quick, and straightforward to use.&lt;/p&gt;

&lt;p&gt;This texture pipeline is implemented as a 2-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export SVG to PNG&lt;/li&gt;
&lt;li&gt;Compress PNG to DDS&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;export-png-from-svg&#34;&gt;Export PNG from SVG&lt;/h3&gt;

&lt;p&gt;Exporting PNG from the source SVG files is done using &lt;a href=&#34;https://inkscape.org&#34; target=&#34;_blank&#34;&gt;Inkscape&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When opening the source SVG files, you will see the pieces laid out like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/art_svg_layout.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Each piece has a unique ID. This ID can be specified when doing an export, and inkspace will export that piece individually.
Since the source data is resolution independent, we need to define the resolution we want to bake the results into a texture.&lt;/p&gt;

&lt;p&gt;The export can be expressed in a straightforward form:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Ninja&#34;&gt;
rule export_svg
  command = C:\Program Files\Inkscape\inkscape.com --export-dpi=&amp;quot;48&amp;quot; --without-gui $in --export-png=$out --export-id=&amp;quot;$export_id&amp;quot;

build tmp_data/textures/KawaiiCookieAssetPack/gameplay_background_tall.png: export_svg src_data/textures/KawaiiCookieAssetPack/SVGs/hud-pieces.svg
    export_id = g86363

build tmp_data/textures/KawaiiCookieAssetPack/gameplay_bottom_border.png: export_svg src_data/textures/KawaiiCookieAssetPack/SVGs/hud-pieces.svg
    export_id = g36017

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First the export_svg rule is defined.
A rule defines a command, which is what executable and the arguments that should be passed to execute the build step.
Ninja contains support for build-in variables such as &lt;code&gt;$in&lt;/code&gt;, &lt;code&gt;$out&lt;/code&gt;, and custom variables such as &lt;code&gt;$export_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The build line defines the output file on the left (&lt;code&gt;$out&lt;/code&gt;), the rule in the middle, and the input file (&lt;code&gt;$in&lt;/code&gt;) on the right.
Additional arguments can be defined for each build step.&lt;/p&gt;

&lt;p&gt;With this setup, Ninja can execute the build. The steps will run in parallel if possible and use incremental compilation.&lt;/p&gt;

&lt;h3 id=&#34;compress-png-to-dds&#34;&gt;Compress PNG to DDS&lt;/h3&gt;

&lt;p&gt;The resulting PNG file are compressed to DDS.
For this the compression I use &lt;a href=&#34;https://github.com/Microsoft/DirectXTex/wiki/Texconv&#34; target=&#34;_blank&#34;&gt;TexConv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have a slightly modified version that adds an additional -of command line option.
It&amp;rsquo;s a small code change that allows exporting to a specified output file. This way the tool fits better into the Ninja design.&lt;/p&gt;

&lt;p&gt;The small code change can be found in my &lt;a href=&#34;https://github.com/jendrikillner/DirectXTex/tree/develop&#34; target=&#34;_blank&#34;&gt;fork&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the Ninja setup the dds compression follows the same pattern.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ninja&#34;&gt;rule convert_to_dds_bc1
  command = ../build_environment/directxtex/texconv.exe -f BC1_UNORM -m 1 -y -of $out $in

rule convert_to_dds_rgba8
  command = ../build_environment/directxtex/texconv.exe -f R8G8B8A8_UNORM_SRGB -m 1 -y -of $out $in 

build target_data/textures/KawaiiCookieAssetPack/gameplay_background_tall.dds: convert_to_dds_bc1   tmp_data/textures/KawaiiCookieAssetPack/gameplay_background_tall.png
build target_data/textures/KawaiiCookieAssetPack/gameplay_bottom_border.dds:   convert_to_dds_rgba8 tmp_data/textures/KawaiiCookieAssetPack/gameplay_bottom_border.png
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;dependency-tracking&#34;&gt;Dependency tracking&lt;/h3&gt;

&lt;p&gt;With this setup, Ninja will detect that DDS compression input files are the SVG export output and will schedule them in the correct order.
Next time the SVG file is changed, Ninja will detect the change, re-export the PNG, and recompress DDS&amp;rsquo;s output.&lt;/p&gt;

&lt;h2 id=&#34;rust-texture-setup&#34;&gt;Rust Texture Setup&lt;/h2&gt;

&lt;p&gt;With all the textures exported into a game-ready format a few more steps are required to actually draw the textures as part of the game.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;load the texture from the disk&lt;/li&gt;
&lt;li&gt;create a D3D11 texture object&lt;/li&gt;
&lt;li&gt;update shader to allow sampling from a shader&lt;/li&gt;
&lt;li&gt;bind the texture view to the pipeline&lt;/li&gt;
&lt;li&gt;issue the draw calls&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;loading-textures&#34;&gt;Loading Textures&lt;/h3&gt;

&lt;p&gt;The first step is to load the texture data from the disk. In the previous part, I described my DDS parser design that accepts a slice of the data.
The same process for loading data as described in &lt;a href=&#34;https://www.jendrikillner.com/post/rust-game-part-6/&#34; target=&#34;_blank&#34;&gt;part 6&lt;/a&gt; for shader loading applies here as well.&lt;/p&gt;

&lt;p&gt;The following helper function will read the file, parse the DDS header, and create the texture.
No real error handling. If a texture is missing, this will panic and crash the process.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub fn load_dds_from_file&amp;lt;&#39;a&amp;gt;(
    filename: &amp;amp;str,
    device: &amp;amp;&#39;a GraphicsDevice,
) -&amp;gt; Result&amp;lt;Texture&amp;lt;&#39;a&amp;gt;, ()&amp;gt; {
    // load the texture data
    let data = std::fs::read(filename).unwrap();

    // parse the header
    let texture_load_result = dds_parser::parse_dds_header(&amp;amp;data).unwrap();

    create_texture(
        device,
        texture_load_result.desc,
        texture_load_result.subresources_data,
    )
}

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;texture-interface&#34;&gt;Texture Interface&lt;/h3&gt;

&lt;p&gt;Each texture has an ID3D11Texture2D and a Shader Resource View (SRV) that allows it to be bound to the pipeline.
Both the texture and the ShaderResourceView have lifetime annotations so that the lifetimes can be validated.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;
pub struct ShaderResourceView&amp;lt;&#39;a&amp;gt; {
    pub native_view: &amp;amp;&#39;a mut winapi::um::d3d11::ID3D11ShaderResourceView,
}

impl Drop for ShaderResourceView&amp;lt;&#39;_&amp;gt; {
    fn drop(&amp;amp;mut self) {
        leak_check_release(self.native_view, 0, None);
    }
}

pub struct Texture&amp;lt;&#39;a&amp;gt; {
    pub native_texture: &amp;amp;&#39;a mut winapi::um::d3d11::ID3D11Texture2D,
    pub srv: ShaderResourceView&amp;lt;&#39;a&amp;gt;,
}

impl Drop for Texture&amp;lt;&#39;_&amp;gt; {
    fn drop(&amp;amp;mut self) {
        leak_check_release(self.native_texture, 0, None);
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;texture-creation&#34;&gt;Texture creation&lt;/h3&gt;

&lt;p&gt;Texture creation is shown below. It&amp;rsquo;s only calling the necessary D3D11 API calls.
Same Rust patterns as discussed in previous parts apply here as well.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;
pub fn create_texture&amp;lt;&#39;a&amp;gt;(
    device: &amp;amp;GraphicsDevice,
    texture_desc: D3D11_TEXTURE2D_DESC,
    subresources_data: Vec&amp;lt;D3D11_SUBRESOURCE_DATA&amp;gt;,
) -&amp;gt; Result&amp;lt;Texture&amp;lt;&#39;a&amp;gt;, ()&amp;gt; {
    let mut texture: *mut winapi::um::d3d11::ID3D11Texture2D = std::ptr::null_mut();
    let mut texture_view: *mut winapi::um::d3d11::ID3D11ShaderResourceView = std::ptr::null_mut();

    unsafe {
        let hr =
            device
                .native
                .CreateTexture2D(&amp;amp;texture_desc, subresources_data.as_ptr(), &amp;amp;mut texture);

        if hr != S_OK {
            return Err(());
        }

        // create a resource view
        let hr = device.native.CreateShaderResourceView(
            texture as *mut winapi::um::d3d11::ID3D11Resource,
            std::ptr::null_mut(),
            &amp;amp;mut texture_view,
        );

        if hr != S_OK {
            return Err(());
        }
    }

    Ok(Texture {
        native_texture: unsafe { texture.as_mut().unwrap() },
        srv: ShaderResourceView {
            native_view: unsafe { texture_view.as_mut().unwrap() },
        },
    })
}

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;drawing-pixel-perfect-textures&#34;&gt;Drawing Pixel Perfect Textures&lt;/h2&gt;

&lt;p&gt;Now that we have the necessary functionality to load, we still need to draw the textures.&lt;/p&gt;

&lt;h3 id=&#34;coordinate-system&#34;&gt;Coordinate system&lt;/h3&gt;

&lt;p&gt;I defined my &amp;ldquo;Game-Space,&amp;rdquo; aka World Space as&lt;/p&gt;

&lt;p&gt;X-Axis: To the right
Y-Axis: Going up&lt;/p&gt;

&lt;p&gt;I want my sprites to be pixel-perfect and always be drawn aligned to the pixel grid.
Therefore I decided to use pixels as my units.&lt;/p&gt;

&lt;p&gt;There are a few articles on how to archive pixel perfect sprite rendering with &lt;a href=&#34;https://ocias.com/blog/unity-pixel-art-camera/&#34; target=&#34;_blank&#34;&gt;Unity&lt;/a&gt; and &lt;a href=&#34;https://weareludicrous.com/blog/2018/3-tricks-to-improve-pixel-art-rendering-in-ue4/&#34; target=&#34;_blank&#34;&gt;UE4&lt;/a&gt; but I could not find one if you are writing your own rendering logic.&lt;/p&gt;

&lt;p&gt;The core of the solution is this.
Each vertex needs to be aligned to a pixel on the output grid.
For me, the solution is simple:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-hlsl&#34;&gt;
float4 TransformWorldToScreen(int2 world_space_pos)
{
    float2 screen_space_pos = float2(
        (world_space_pos.x / ScreenWidth) * 2 - 1,
        (world_space_pos.y / ScreenHeight) * 2 - 1);

    return float4(screen_space_pos, 0, 1);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;world_space_pos is in pixels and, therefore, always aligned to the grid. If another unit is used, it&amp;rsquo;s essential to make sure that screen_space_pos always refers to positions aligned to the screen&amp;rsquo;s pixel grid.&lt;/p&gt;

&lt;p&gt;Here are a few pointers on how to make sure your rendering is correct.&lt;/p&gt;

&lt;h2 id=&#34;debugging-advice&#34;&gt;Debugging advice&lt;/h2&gt;

&lt;p&gt;Create a 64x64 black and white checkerboard.&lt;/p&gt;

&lt;p&gt;Such as this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/black_white_grid_64x64.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Draw this texture onto a quad of the same size and use linear texture sampler.&lt;/p&gt;

&lt;p&gt;With linear sampling, blending will occur between neighboring pixels if they are not perfectly aligned to the pixel grid.
Doing this will highlight any errors that might occur in the calculation.&lt;/p&gt;

&lt;p&gt;The result on screen should show the checkerboard pattern.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/correct_positioning.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;If you take a magnifying glass or enlarge this image, you should still see the checkerboard.
Without any repeating or skipped pixels anywhere on your quads.&lt;/p&gt;

&lt;p&gt;If the pattern turns into anything else, such as a gray quads. Something went wrong along the drawing pipeline&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/incorrect_positioning.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;There can be a lot of reasons, you might be applying half a pixel offset, rounding incorrectly, projecion doesn&amp;rsquo;t match the windows size etc&lt;/p&gt;

&lt;h2 id=&#34;drawing-the-game&#34;&gt;Drawing the game&lt;/h2&gt;

&lt;p&gt;Now we have all the ingredients to draw the base of the game:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/base_game_stage0.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;The state of the item grid is stored as a 2-dimensional array of booleans right now.
6 rows, each with 5 entries for each row&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;
pub struct GameplayStateFrameData {
    // the state of the grid
    grid: [[bool; 5]; 6],
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can then use Rust iterators to iterate over the whole grid.
With .enumerate() we get access to both the index and the value.&lt;/p&gt;

&lt;p&gt;This is useful in a case like these where both the value and the index are required for the logic.
In this example, the index is used to calculate the position. The boolean values decide the color of the quad.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;
for (y, row) in frame_params.grid.iter().enumerate() {
    for (x, column) in row.iter().enumerate() {
        let x_offset_in_pixels = (x * 91) as i32;
        let y_offset_in_pixels = (y * 91) as i32;

        // allocate the constants for this draw call
        let obj_alloc = HeapAlloc::new(
            GameSpaceQuadData {
                color: if !column {
                    Float4 {
                        x: 1.0,
                        y: 1.0,
                        z: 1.0,
                        a: 1.0,
                    }
                } else {
                    Float4 {
                        x: 0.0,
                        y: 1.0,
                        z: 0.0,
                        a: 1.0,
                    }
                },
                size_pixels: Int2 { x: 90, y: 90 },
                position_bottom_left: Int2 {
                    x: 45 + x_offset_in_pixels,
                    y: 960 - 330 + 45 - y_offset_in_pixels,
                },
            },
            gpu_heap_data,
            gpu_heap_state,
        );

        bind_constant(command_list, 0, &amp;amp;obj_alloc);

        draw_vertices(command_list, 4);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With all this put together, we now have the drawing logic setup for the game.
The game flow is in-place. We can swap between different game screens, react to player input, and draw the game world.&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;The next part will be all about implementing the actual Match 3 mechanics.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-15&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 14 - DDS Parser</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-14/</link>
      <pubDate>Tue, 15 Sep 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-14/</guid>
      <description>

&lt;p&gt;This is the first part about the texture loading implementation for the Match 3 game.&lt;/p&gt;

&lt;p&gt;In this part, I am going to cover&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Error Handling&lt;/li&gt;
&lt;li&gt;Unit testing&lt;/li&gt;
&lt;li&gt;Integration Testing&lt;/li&gt;
&lt;li&gt;Development Only Dependencies&lt;/li&gt;
&lt;li&gt;Parsing binary files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lots to talk about, so let us get started.&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;Textures formats such as png and jpg are aimed at reducing size on disk. But GPUs cannot read these directly, and therefore texture data needs to be decompressed before they can be read.&lt;/p&gt;

&lt;p&gt;Block compressed formats allow texture data to remain compressed at all times. This reduces memory usage and reduces memory bandwidth when accessing the textures; an example of a block compressed format is .dds&lt;/p&gt;

&lt;p&gt;The process for loading DDS files can be broken down into 4 high-level steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parse the DDS file and unpack the texture data&lt;/li&gt;
&lt;li&gt;Create a D3D11 texture from the data parsed information&lt;/li&gt;
&lt;li&gt;Update the shaders to enable reading from textures&lt;/li&gt;
&lt;li&gt;Bind the texture to the pipeline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This blog post will only cover step 1 and 2&lt;/p&gt;

&lt;p&gt;The .dds format is fundamentally quite simple, but the number of variations and exceptions makes it a tricky format to parse in practice.&lt;/p&gt;

&lt;p&gt;For this example parser implementation, I will restrict myself to only what is required for the time being.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;2D Textures only&lt;/li&gt;
&lt;li&gt;BC1 to BC7 + uncompressed RGBA8&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To learn more about the different BC formats, I recommend this article &lt;a href=&#34;https://web.archive.org/web/20200624115519/http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/&#34; target=&#34;_blank&#34;&gt;Understanding BCn Texture Compression Formats&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;

&lt;p&gt;The DDS parser receives a binary blob of data, parses the necessary information, and fills out the D3D11 descriptors.&lt;/p&gt;

&lt;p&gt;In Rust function terms, it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub struct ParsedTextureData {
    pub desc: D3D11_TEXTURE2D_DESC,
    pub subresources_data: Vec&amp;lt;D3D11_SUBRESOURCE_DATA&amp;gt;,
}

pub fn parse_dds_header(src_data: &amp;amp;[u8]) -&amp;gt; Result&amp;lt;ParsedTextureData, DdsParserError&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The function returns a &lt;code&gt;Result&amp;lt;ParsedTextureData, DdsParserError&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h1 id=&#34;error-handling&#34;&gt;Error handling&lt;/h1&gt;

&lt;p&gt;I tend to think about error handling in two distinct categories.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unexpected Failure&lt;/li&gt;
&lt;li&gt;Expected Failure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I prefer the program to &lt;a href=&#34;https://doc.rust-lang.org/std/macro.panic.html&#34; target=&#34;_blank&#34;&gt;panic&lt;/a&gt; and abandon the application for unexpected failure. These kinds of failures happen if the application enters a state that was never expected to happen.&lt;/p&gt;

&lt;p&gt;I prefer to panic early so that the application crashes as soon as an invalid state is detected instead of causing more subtle and hard to debug problems.&lt;/p&gt;

&lt;p&gt;For expected failure cases, Rust offers an excellent method build around &lt;a href=&#34;https://doc.rust-lang.org/std/result/&#34; target=&#34;_blank&#34;&gt;Result&lt;/a&gt;. This type is used to represent a return value that can either contain a success or failure value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;parse_dds_header&lt;/code&gt; will return a DdsParserError in case of failure, and only if parsing was successful, the ParsedTextureData is returned.&lt;/p&gt;

&lt;p&gt;Currently, the parser returns the following error codes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub enum DdsParserError {
    InvalidHeader(&amp;amp; &#39;static str),
    InvalidFlags(&amp;amp; &#39;static str),
    FormatNotSupported,
    ImageSizeNotMultipleOf4,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In my opinion, each function that can fail should return a unique error enum that lists all possible failure cases.
This way, it&amp;rsquo;s apparent to the caller what kind of failures can be expected and can decide how to handle each possibility.&lt;/p&gt;

&lt;p&gt;If you would like to learn more about Error Handling in Rust, look at this talk &lt;a href=&#34;https://www.youtube.com/watch?v=rAF8mLI0naQ&#34; target=&#34;_blank&#34;&gt;RustConf 2020 - Error handling Isn&amp;rsquo;t All About Errors by Jane Lusby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Great talk; I disagree with Jane on the use of &lt;a href=&#34;https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute&#34; target=&#34;_blank&#34;&gt;non_exhaustive&lt;/a&gt; however.&lt;/p&gt;

&lt;p&gt;Rust enums need to be exhaustively matched by default (meaning all possible cases need to be handled).
Therefore each addition of a new valie will also be a breaking API change.&lt;/p&gt;

&lt;p&gt;If you have a custom error enum for each function, then introducing a new error value means the function has a new Expected Failure case that didn&amp;rsquo;t exist before.&lt;/p&gt;

&lt;p&gt;This is a breaking API change and should force all users to think about how to handle the new failure case.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;non_exhaustive&lt;/code&gt; hides the introduction of a new failure from the user.
And a user might only detect that a new error was introduced when the error happens at runtime instead of seeing the new unhandled error case at compile time.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think that&amp;rsquo;s the right decision but decide that for yourself.&lt;/p&gt;

&lt;h3 id=&#34;testing&#34;&gt;Testing&lt;/h3&gt;

&lt;p&gt;We had a look at the API and how to handle different failure cases.
The API surface is minimal and makes for a great candidate to show two types of testing supported by Cargo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit Testing&lt;/li&gt;
&lt;li&gt;Integration Testing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unit testing is a testing level where individual components of an application are tested in isolation with optimally no dependencies on other components.&lt;/p&gt;

&lt;p&gt;Integration tests verify that the interactions of two or more components achieve the expected goal.&lt;/p&gt;

&lt;p&gt;For this parser, the tests are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit Test: validate that the expected information is returned&lt;/li&gt;
&lt;li&gt;Integration test: validate that the returned information also creates valid D3D11 texture&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&#34;unit-testing&#34;&gt;Unit Testing&lt;/h4&gt;

&lt;p&gt;Adding a Unit Tests to a Rust project is simple.&lt;/p&gt;

&lt;p&gt;Just add the following code to any rust file, and you got yourself a Unit Test.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub fn add_two(a: i32) -&amp;gt; i32 {
    a + 2
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_adds_two() {
        assert_eq!(4, add_two(2));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Running &lt;code&gt;cargo test&lt;/code&gt; will run all unit tests found in the current project.&lt;/p&gt;

&lt;p&gt;The same concept in a more complete example from the parser is below.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;#[test]
fn validate_texture_header_black_4x4_bc1() {
    let texture_header_ref = D3D11_TEXTURE2D_DESC {
        ...
    };

    let texture_data_desc = D3D11_SUBRESOURCE_DATA {
        pSysMem: std::ptr::null_mut(), // can&#39;t validate this, will be pointing into the dynamic memory adresse
        SysMemPitch: 8,                // 4x4 texture = 1 BC1 block = 8 bytes
        SysMemSlicePitch: 8,           // 1 block
    };

    let texture_load_result = parse_dds_header(paintnet::BLACK_4X4_BC1);

    assert_eq!(texture_load_result.is_ok(), true);

    let texture_header = texture_load_result.unwrap();

    validate_texture_header(&amp;amp;texture_header_ref, &amp;amp;texture_header.desc);

    // should contain one subresource
    assert_eq!(texture_header.subresources_data.len(), 1);

    assert_eq!(
        texture_data_desc.SysMemPitch,
        texture_header.subresources_data[0].SysMemPitch
    );
    assert_eq!(
        texture_data_desc.SysMemSlicePitch,
        texture_header.subresources_data[0].SysMemSlicePitch
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Firstly we define what values the D3D11 header is supposed to contain.
We then use several &lt;code&gt;assert_eq&lt;/code&gt; to validate that the parser&amp;rsquo;s values are what we expected.&lt;/p&gt;

&lt;p&gt;One part that stands out is how the texture parsing is called.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;let texture_load_result = parse_dds_header(paintnet::BLACK_4X4_BC1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might remember that the function accepts a slice to binary data as a parameter.
But how do we get access to the data that contains the texture?&lt;/p&gt;

&lt;p&gt;One option would be to load the file from disk. However, loading from disk can fail for several reasons.
Instead of introducing opportunities for random failures, I am embedding the file directly into the unit test executable.&lt;/p&gt;

&lt;p&gt;Rust provides a very convenient macro for this. This macro takes any file (path is relative to the current file) and will embed the binary data directly into the executable.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;// embed the data we will be testing against
mod paintnet {
    pub static BLACK_4X4_BC1: &amp;amp;&#39;static [u8; 136] =
        include_bytes!(&amp;quot;../tests/data/paintnet/black_4x4_bc1.dds&amp;quot;);
    pub static BLACK_4X4_MIPS_BC1: &amp;amp;&#39;static [u8; 152] =
        include_bytes!(&amp;quot;../tests/data/paintnet/black_4x4_mips_bc1.dds&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is ideal for small binary files, such as the texture data used for the unit tests.&lt;/p&gt;

&lt;p&gt;For the parser, I only used a unit test to get the first parsing logic verified but did all other testing using integration testing.&lt;/p&gt;

&lt;h3 id=&#34;integration-testing&#34;&gt;Integration Testing&lt;/h3&gt;

&lt;p&gt;The integration tests will verify that parsed texture information will create a valid texture.
Valid in this context means that the D3D11 debug layer will not generate any warnings or errors.&lt;/p&gt;

&lt;p&gt;It does not mean that the texture actually looks like we expect it.
For example, if we are expecting all pixels to be black, but for some reason, they are red, these integration tests will not fail.&lt;/p&gt;

&lt;p&gt;From a code perspective, integration tests look the same:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;#[test]
fn load_and_create_black_4x4_bc1() {
    test_texture_load_and_creation2( paintnet::BLACK_4X4_BC1 );
}

#[test]
fn load_and_create_black_4x4_mips_bc1() {
    test_texture_load_and_creation2( paintnet::BLACK_4X4_MIPS_BC1 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Integration tests are located in a separate directory from the code they are testing.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dds_parser
    - src/
        dds_parser_lib.lib // Unit tests
    - tests/
        dds_parser_integration_tests.lib // Integration tests
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This also means integration tests are located in a separate module and are only allowed to call the public interface.&lt;/p&gt;

&lt;p&gt;All integration tests for the parser call a single function with different binary data, as you saw above.
The function implementation looks like below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;fn test_texture_load_and_creation(data: &amp;amp;[u8]) {
    let debug_device = true;
    let graphics_layer: GraphicsDeviceLayer =
        graphics_device::create_device_graphics_layer_headless(debug_device).unwrap();

    // parse the header
    let texture_load_result = dds_parser::parse_dds_header(&amp;amp;data).unwrap();

    let (_texture, _texture_view) = graphics_device::create_texture(
        &amp;amp;graphics_layer.device,
        texture_load_result.desc,
        texture_load_result.subresources_data,
    )
    .unwrap();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s a 3 step process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the Graphics layer&lt;/li&gt;
&lt;li&gt;Parse the DDS header information&lt;/li&gt;
&lt;li&gt;pass the parsed data into the &lt;code&gt;create_texture&lt;/code&gt; function&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every step is followed by an unwrap() call; this will ensure that if any of the steps fails, the integration test will also fail.&lt;/p&gt;

&lt;p&gt;One beneficial aspect of the Rust testing framework is that we can also test for expected failures:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;#[test]
#[should_panic(expected = r#&amp;quot;called `Result::unwrap()` on an `Err` value: InvalidDimensions&amp;quot;#)]
fn load_and_create_black_5x4_bc1() {
    test_texture_load_and_creation(&amp;quot;paintnet/white_5x4_bc1.dds&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here I tell Cargo that this test is expected to panic and that the panic message should contain a specified text.
This is very useful to make sure that invalid data triggers the Expected Failure case you expected to happen.&lt;/p&gt;

&lt;p&gt;I am verifying that the parser correctly detects textures that are not a multiple of the block size.&lt;/p&gt;

&lt;p&gt;You might have noticed one problem with the integration test setup in terms of library dependencies.
The integration tests are part of the &lt;code&gt;dds_parser&lt;/code&gt; crate, and we are using the &lt;code&gt;graphics_device&lt;/code&gt; crate for the integration tests.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t really want to introduce a dependency on the &lt;code&gt;graphics_device&lt;/code&gt; crate just to use it for integration tests.&lt;/p&gt;

&lt;p&gt;But Cargo has a trick up its sleeve to deal with this situation.&lt;/p&gt;

&lt;h2 id=&#34;development-only-dependencies&#34;&gt;Development Only Dependencies&lt;/h2&gt;

&lt;p&gt;These kinds of dependencies are used to specify dependencies that are only required for tests or benchmarks.&lt;/p&gt;

&lt;p&gt;These are added to the cargo.toml, just like other dependencies.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Toml&#34;&gt;[dev-dependencies]
graphics_device = { path = &amp;quot;../graphics_device&amp;quot; }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The difference is that these dependencies are not propagated to users of a crate.&lt;/p&gt;

&lt;p&gt;In this case, using the &lt;code&gt;dds_parser&lt;/code&gt; will not create a dependency on &lt;code&gt;graphics_device&lt;/code&gt;.
But all tests still have full access to all functionality of the &lt;code&gt;graphics_device&lt;/code&gt; crate just as if it would be a regular dependency.&lt;/p&gt;

&lt;h2 id=&#34;reading-binary-files&#34;&gt;Reading binary files&lt;/h2&gt;

&lt;p&gt;After looking at testing, error handling strategy, and testing dependencies, we miss one crucial part.
How to actually parse a .dds file.&lt;/p&gt;

&lt;p&gt;This process is quite long; please have a look at &lt;code&gt;dds_parser\src\dds_parser_lib.rs&lt;/code&gt; in the code provided on GitHub to see all the details.&lt;/p&gt;

&lt;p&gt;I will provide an introduction to how I decided to approach parsing binary files using Rust without crates.&lt;/p&gt;

&lt;p&gt;The DDS format is broken into distinct parts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DWORD with value &amp;ldquo;DDS &amp;rdquo; 0x20534444&lt;/li&gt;
&lt;li&gt;DDS_HEADER&lt;/li&gt;
&lt;li&gt;optionally: DDS_HEADER_DXT10&lt;/li&gt;
&lt;li&gt;BYTES (main surface data)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The file starts with a DWORD that contains a &amp;ldquo;magic value&amp;rdquo;.
This concept can be found in many file formats and is an easy way to detect if the data provided could be a valid DDS file.&lt;/p&gt;

&lt;p&gt;A DWORD refers to a double word, or also known as 32-bit unsigned integer.&lt;/p&gt;

&lt;p&gt;This is the start of the parser:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub fn parse_dds_header(src_data: &amp;amp;[u8]) -&amp;gt; Result&amp;lt;ParsedTextureData, DdsParserError&amp;gt; {

    // a valid DDS file needs at least 128 bytes to store the DDS dword and DDS_HEADER
    // if the file is smaller it cannot be a valid file
    if src_data.len() &amp;lt; 128 {
        return Err(DdsParserError::InvalidHeader(&amp;quot;smaller than 128 bytes&amp;quot;));
    }

    let mut file_cursor = 0;

    // DDS files are expected to start with &amp;quot;DDS &amp;quot; = 0x20534444
    // if this is not the case the file is not a valid DDS file
    // try_into could panic if src_data is too short
    // but we checked the data length before
    let dw_magic: u32 =
        u32::from_le_bytes(src_data[file_cursor..(file_cursor + 4)].try_into().unwrap());
    file_cursor += 4;

    if dw_magic != 0x2053_4444 {
        return Err(DdsParserError::InvalidHeader(
            &amp;quot;file is missing DDS DWORD at start of the file&amp;quot;,
        ));
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, we validate that the file is large enough to store the minimum information required.
If the file is smaller, it cannot be a valid DDS file, and we return an error code to indicate this.&lt;/p&gt;

&lt;p&gt;Then we parse the magic dword that is expected to be at the start of the file.
Rust provides a few functions to enable parsing for primitive types such as u32.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;from_le_bytes(bytes: [u8; 4]) -&amp;gt; u32
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This function accepts a slice of 4 bytes and returns a u32.
The _le refers to little-endian byte order as opposed to big-endian.
Refer to &lt;a href=&#34;https://web.archive.org/web/20200501222745/https://chortle.ccsu.edu/AssemblyTutorial/Chapter-15/ass15_3.html&#34; target=&#34;_blank&#34;&gt;for the difference&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how do we convert a slice of unknown length into a fixed-length slice?
The way to achieve this might not be immediately apparent.&lt;/p&gt;

&lt;p&gt;The solution is this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;let u32slice : [u8;4] = src_data[0..4].try_into().unwrap()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But how did I end up with this?&lt;/p&gt;

&lt;p&gt;The first apparent thing to try would be&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;let u32slice : [u8;4] = src_data[0..4]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I did this and expected it to work because clearly, we know these are 4 entries, and the compiler should figure this out too.&lt;/p&gt;

&lt;p&gt;So let us try this and see what the compiler thinks:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;1&amp;gt;49 | let u32slice : [u8;4] = src_data[0..4];
1&amp;gt;   |                ------   ^^^^^^^^^^^^^^ expected array `[u8; 4]`, found slice `[u8]`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But it&amp;rsquo;s not so easy. This will only work if we are 100% sure that the slice is at least 4 u8 entries long.
We cannot guarantee this since &lt;code&gt;src_data: &amp;amp;[u8]&lt;/code&gt; is of unknown length.&lt;/p&gt;

&lt;p&gt;So what can we do instead?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;1&amp;gt;49 | let u32slice : [u8;4] = src_data[0..4].try_into();
1&amp;gt;   |                ------   ^^^^^^^^^^^^^^^^^^^^^^^^^ expected array `[u8; 4]`, found enum `std::result::Result`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok, we are getting closer.
TryInto is a trait that allows types to be converted into another type.
These support conversions that might fail or could be expensive.&lt;/p&gt;

&lt;p&gt;As you can see above, try_into returns a Result. So we should handle the failure condition.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;let u32slice : [u8;4] = src_data[0..4].try_into().unwrap()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the parser, I use unwrap() on the result.
This call could fail if the slice doesn&amp;rsquo;t contain enough bytes for the requested range.
But we covered this case with an earlier if that validates that we have at least 128 bytes of data.&lt;/p&gt;

&lt;p&gt;With this slice, we can now parse the data.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;let dw_magic: u32 =
        u32::from_le_bytes(u32slice);

if dw_magic != 0x2053_4444 {
        return Err(DdsParserError::InvalidHeader);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And with that, we have done all the necessary parsing steps to parse a u32 value from a binary file.&lt;/p&gt;

&lt;p&gt;If you had a look at the code on GitHub, you would see the line looks slightly different.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;src_data[file_cursor..(file_cursor + 4)].try_into().unwrap()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What is file_cursor?&lt;/p&gt;

&lt;p&gt;I tend to use a single variable to store how many bytes have been parsed and make all parsing operations relative to the file&amp;rsquo;s progress.&lt;/p&gt;

&lt;p&gt;This makes the parser easier to read, and it also makes it possible to do a quick sanity check at the end of the parser.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;// all data needs to be used, otherwise therer was a problem with parsing
assert!(file_cursor == src_data.len());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we reached the parsing logic&amp;rsquo;s end, we should have parsed each byte in the file.
If not, there might be a bug in the parsing logic, or the file contains sections that we didn&amp;rsquo;t process.&lt;/p&gt;

&lt;p&gt;This is an unexpected failure case, better to fail early, and let us know we have a problem with the parser logic.
If you expect your parser to be used on untrusted data, you might want to make this an expected failure case instead.&lt;/p&gt;

&lt;p&gt;With this, we have seen the core of the parsing logic; the same idea is applied to many more entries in the DDS file.&lt;/p&gt;

&lt;p&gt;If you are interested in the DDS specifics, look at the &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-14&#34; target=&#34;_blank&#34;&gt;Github code&lt;/a&gt;, and if you have any questions, feel free to comment below or send me a message.&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s all good, we seem to be able to load D3D11 textures, but we will not be sure that they actually work until we have seen them.&lt;/p&gt;

&lt;p&gt;So how do we render the textures on the screen?&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s a topic for the next post :)&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-14&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 13 - Modules</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-13/</link>
      <pubDate>Wed, 20 May 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-13/</guid>
      <description>

&lt;h2 id=&#34;goal&#34;&gt;Goal&lt;/h2&gt;

&lt;p&gt;At the end of this post, the game state management will be separated into multiple files.
The Rust module system is taken advantage of to further separate public interfaces from implementation details.&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;Right now, the functionality for both supported game states (Pause and Gameplay) is contained in main.rs and caused this file to grow to an unwieldy 500+ lines.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s time to split this file up. The two options are modules in separate files or crates.
For this purpose, I think crates are overkill, and I will be moving it into a hierarchy of modules.&lt;/p&gt;

&lt;h3 id=&#34;hierarchy-of-modules&#34;&gt;Hierarchy of modules&lt;/h3&gt;

&lt;p&gt;In Rust, each file implicitly defines a module of the same name as the file.
Adding a file called pause.rs, for example, will create a pause module.
Files structured in a hierarchy will also define a hierarchical module structure.&lt;/p&gt;

&lt;p&gt;With this in mind the file structure I decided on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;src/
  main.rs
  gamestates.rs
  gamestates/
    pause.rs
    gameplay.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Therefore the pause state functionality will be found in &lt;code&gt;gamestates::pause&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and the gameplay in
&lt;code&gt;gamestates::gameplay&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The gamestates.rs and the folder gamestates belong together.
This is one of the two option to define the root of a module.&lt;/p&gt;

&lt;p&gt;There is another option using a file called mod.rs such as this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;src/
  main.rs
  gamestates/
    pause.rs
    gameplay.rs
    mod.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This was the only way until Rust 2018, but I prefer the new way because it makes it easier to search for a file by name.&lt;/p&gt;

&lt;p&gt;Imaging your project grows, and you might have a lot of modules and therefore, a lot of files called mod.rs.
This sounds like a nightmare to find to me.&lt;/p&gt;

&lt;p&gt;But what is the purpose of mod.rs or gamestates.rs?&lt;/p&gt;

&lt;p&gt;For a module to be included in the compilation, it needs to be referenced.
This is done using the mod keyword. I like to put these at the top of the files, so it&amp;rsquo;s easy to see.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;// these make sure we compile the modules
mod gamestates;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This statement will cause the gamestates module to be compiled for the current compilation unit.
&lt;code&gt;gamestates.rs&lt;/code&gt; then list all the modules that will be included in the compilation if gamestates is requested.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;// compile all the game states
mod gameplay;
mod pause;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Additionally, you might include functionality in this file that connects the pieces of the child modules together.
I am doing that, more on that later.&lt;/p&gt;

&lt;p&gt;For now, we only have created the file structure but not moved any code around.&lt;/p&gt;

&lt;h3 id=&#34;moving-code-into-modules&#34;&gt;Moving code into modules&lt;/h3&gt;

&lt;p&gt;With the file structure created we can copy all the PauseState related functionality into pause.rs.
Only doing that is, of course, not enough. A lot of errors along these lines are greeting me.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error[E0425]: cannot find function `create_pso` in this scope
--&amp;gt; match3_game\src\gamestates\pause.rs:13:66
|
|         let screen_space_quad_blended_pso: PipelineStateObject = create_pso(
|                                                                  ^^^^^^^^^^ not found in this scope
| help: possible candidate is found in another module, you can import it into scope
|
| use graphics_device::create_pso;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The compiler is very helpful and tells you quite detailed what the problem is.
By default, we can only access functions, structs, &amp;hellip; that are defined in the same module.&lt;/p&gt;

&lt;p&gt;If we want to access these elements, we need to explicitly opt-in. And the compiler error shows one of the possible ways to resolve it.&lt;/p&gt;

&lt;p&gt;If you are using the Rust extension for &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=dos-cafe.Rust&#34; target=&#34;_blank&#34;&gt;Visual Studio&lt;/a&gt; it will provide you a quick fix for this error:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/visual_studio_quick_help.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;There are multiple ways to achieve this, see the &lt;a href=&#34;https://doc.rust-lang.org/1.27.2/book/second-edition/ch07-03-importing-names-with-use.html&#34; target=&#34;_blank&#34;&gt;rust book&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;But the TLDR version is:&lt;/p&gt;

&lt;p&gt;If we have multiple imports from the same module, we can group them&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;// instead of listing them individually
use graphics_device::create_pso;
use graphics_device::create_texture;

// grouped imports from graphics_device module
use graphics_device::{create_pso, create_texture};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To reference something one level above us in the hierarchy use&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;use super::GameStateType
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To reference something defined in the root of the crate use&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;use crate::Float2;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Having fixed up all the missing references, we are greeted with a new error from main.rs&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use crate::pause::PauseStateStaticData;
                   ^^^^^^^^^^^^^^^^^^^^ this struct is private
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reason for this is that by default, all types in Rust are private. They can only be accessed from the current module.
We need explicitly annotate all types and functions that we would like to access from outside the module.&lt;/p&gt;

&lt;p&gt;This can be done like below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Rust&#34;&gt;pub struct PauseStateFrameData {
    fade_in_status: f32,
}

impl PauseState&amp;lt;&#39;_&amp;gt; {
    pub fn new&amp;lt;&#39;a&amp;gt;(device_layer: &amp;amp;GraphicsDeviceLayer) -&amp;gt; PauseState&amp;lt;&#39;a&amp;gt; { ... }
}

pub fn draw_pause_state( ... )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Small gotcha, the impl cannot have a pub modifier.&lt;/p&gt;

&lt;p&gt;We will need to expose all public types that are used directly or are used in a public interface.
If we don&amp;rsquo;t we get errors like these:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error[E0446]: private type `UpdateBehaviourDesc` in public interface
   --&amp;gt; match3_game\src\pause.rs:68:1
    |
68  | / pub fn update_pause_state(
69  | |     prev_frame_params: &amp;amp;PauseStateFrameData,
70  | |     frame_params: &amp;amp;mut PauseStateFrameData,
71  | |     messages: &amp;amp;Vec&amp;lt;WindowMessages&amp;gt;,
...   |
93  | |     }
94  | | }
    | |_^ can&#39;t leak private type
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The error message is, once again, very clear about the problem.
&lt;code&gt;update_pause_state&lt;/code&gt; has been made public but it uses the private type &lt;code&gt;UpdateBehaviourDesc&lt;/code&gt; in the public interface (return type in this case)&lt;/p&gt;

&lt;p&gt;Therefore we need to make that type public too.
This only makes the type public but not the members themselves. So you don&amp;rsquo;t need to worry about outside code modifying members directly.&lt;/p&gt;

&lt;p&gt;Once all these errors are fixed, the game should still run and look exactly the same.
Just the code is easier to manage :)&lt;/p&gt;

&lt;h2 id=&#34;structure-changes&#34;&gt;Structure Changes&lt;/h2&gt;

&lt;p&gt;Furthermore, I decided to move all the game state related logic out of the main game loop.
The logic for switching states, updating and drawing states makes it more challenging to see the core of the main game loop.&lt;/p&gt;

&lt;p&gt;Gamestates.rs is the root of the module and is, therefore, the perfect place to implement such functionality.
It provides the interface between the game and the game states.&lt;/p&gt;

&lt;p&gt;It contains the types:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub enum GameStateType {
    Pause,
    Gameplay,
}

pub enum GameStateTransitionState {
    Unchanged,
    TransitionToNewState(GameStateType),
    ReturnToPreviousState,
}

... 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And functions such as these:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub fn execute_possible_state_transition(
    state_transition: GameStateTransitionState,
    game_state_stack: &amp;amp;mut Vec&amp;lt;GameStateData&amp;gt;,
    graphics_layer: &amp;amp;GraphicsDeviceLayer,
) {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One part to point out for this function is that the ownership of &lt;code&gt;state_transition&lt;/code&gt; is moved into &lt;code&gt;execute_possible_state_transition&lt;/code&gt; and not passed as a reference like all other arguments.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GameStateTransitionState&lt;/code&gt; is used to track how the game states should be updated.
Either we can keep the state unchanged, add a new state, or remove game states.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;execute_possible_state_transition&lt;/code&gt; will do this transition internally the &lt;code&gt;state_transition&lt;/code&gt; we pass in will not be valid after the function returns. Moving ownership into the function makes the original variable unusable, and Rust will throw an error if we forget to reset it afterward&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;115 |     let mut next_game_state: GameStateTransitionState =
    |         ------------------- move occurs because `next_game_state` has type `gamestates::GameStateTransitionState`, which does not implement the `Copy` trait
...
142 |         execute_possible_state_transition( next_game_state, &amp;amp;mut game_state_stack, &amp;amp;graphics_layer );
    |                                            ^^^^^^^^^^^^^^^ value moved here, in previous iteration of loop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This error is not super clear to read at first, but the simplified logic is below.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let mut next_game_state: GameStateTransitionState =
        GameStateTransitionState::TransitionToNewState(GameStateType::Gameplay);

while !should_game_close {
  execute_possible_state_transition(next_game_state, &amp;amp;mut game_state_stack, &amp;amp;graphics_layer);

  // from now on next_game_state is invalid and cannot be acessed
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;next_game_state&lt;/code&gt; is defined before we enter the main loop.
Inside of the loop we move the &lt;code&gt;next_game_state&lt;/code&gt; ownership into the &lt;code&gt;execute_possible_state_transition&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Once this function returns, the original variable cannot be accessed anymore.
Since it lost the ownership of the value.&lt;/p&gt;

&lt;p&gt;The fix for this is quite simple:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;execute_possible_state_transition(next_game_state, &amp;amp;mut game_state_stack, &amp;amp;graphics_layer);
// assign a new value to next_game_state
// therefore we can access it again in the next iteration of the loop
next_game_state = GameStateTransitionState::Unchanged;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I like code being explicit and straightforward, and this clearly shows while scanning the code that the state transition state will be reset after &lt;code&gt;execute_possible_state_transition&lt;/code&gt; returns.&lt;/p&gt;

&lt;p&gt;If we passed it by reference, Rust compiler would not warn, and we might forget to reset the variable.
Causing a run-time logic error instead of a compile-time error.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s it for now. Main.rs is back to ~200 lines of code.
There is more that could be moved around, but I will do that another time when I have a better idea of how the design will evolve.&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;It seems like it&amp;rsquo;s time for some more exciting visuals.
Going to implement texture loading support next.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-13&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 12 - Game States</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-12/</link>
      <pubDate>Mon, 11 May 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-12/</guid>
      <description>

&lt;h2 id=&#34;goal&#34;&gt;Goal&lt;/h2&gt;

&lt;p&gt;At the end of this part, I will have a small prototype. This prototype contains the general game state flow between Gameplay and Pause State.
The gameplay state is rendering a grid and reacting to mouse clicks.&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;I like to keep the states of the game to be independent of each other.
Therefore I am going to focus on the foundation of the state management system before adding actual gameplay functionality.&lt;/p&gt;

&lt;p&gt;All states are managed as a stack.
This allows states like the Pause screen to be used for multiple use-cases. Only the pause state needs to be removed from the stack to return to the previous state.&lt;/p&gt;

&lt;h3 id=&#34;game-state-data-model&#34;&gt;Game State Data Model&lt;/h3&gt;

&lt;p&gt;Each Game State has 2 lifetimes: Static and Frame&lt;/p&gt;

&lt;p&gt;[StaticData]&lt;/p&gt;

&lt;p&gt;[FrameData][FrameData]&lt;/p&gt;

&lt;p&gt;There is a single copy of static data for each GameState.
And two copies of FrameData since I am using a double buffering scheme.&lt;/p&gt;

&lt;h4 id=&#34;static-data&#34;&gt;Static Data&lt;/h4&gt;

&lt;p&gt;Static data is created once and cannot be modified after.
This stores information such as PSOs, textures, and other read-only data.&lt;/p&gt;

&lt;h4 id=&#34;frame-data&#34;&gt;Frame Data&lt;/h4&gt;

&lt;p&gt;The frame data stores all dynamic information about the state.
This includes information like player score, state of the game world, etc.&lt;/p&gt;

&lt;p&gt;The update logic will get a read-only view of the previous frame state. It&amp;rsquo;s expected to read the last state frame as input and generate a new data into the output frame data.&lt;/p&gt;

&lt;p&gt;For this game, I am trying not to in-place modify the game state.
Let&amp;rsquo;s see how this goes :)&lt;/p&gt;

&lt;h3 id=&#34;game-state-api&#34;&gt;Game State API&lt;/h3&gt;

&lt;p&gt;The core of the API are two enums:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub enum GameStateType {
    //MainMenu,
    Pause,
    Gameplay,
}

enum GameStateData&amp;lt;&#39;a&amp;gt; {
    Gameplay(GameplayState&amp;lt;&#39;a&amp;gt;),
    Pause(PauseState&amp;lt;&#39;a&amp;gt;),
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the types being defined like this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;struct GameplayState {
    static_data: GameplayStateStaticData,
    frame_data0: GameplayStateFrameData,
    frame_data1: GameplayStateFrameData,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I would have liked to store the GameplayStateFrameData as an array, but sadly Rust doesn&amp;rsquo;t allow borrowing of individual array entries in a natural way.&lt;/p&gt;

&lt;p&gt;There are ways of doing it using iterators and/or slices. But for this use case, two variables will work just fine.&lt;/p&gt;

&lt;p&gt;These GameStateData blocks are stored in a simple Vec to form a stack:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt; let mut game_state_stack: Vec&amp;lt;GameStateData&amp;gt; = Vec::new();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The state transition are yet another enum, you see I love Rust enums :P
This controls which state to switch and how that state switch should happen&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;
pub enum GameStateTransitionState {
    Unchanged,
    TransitionToNewState(GameStateType),
    ReturnToPreviousState,
}

let mut next_game_state: GameStateTransitionState =
    GameStateTransitionState::TransitionToNewState(GameStateType::Gameplay);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Game state transitions always happen at the beginning of a CPU frame, and the GameState update returns a value specifying if and how state transitions should be done.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;match next_game_state {
    GameStateTransitionState::TransitionToNewState(x) =&amp;gt; {
        match x {
            GameStateType::Gameplay =&amp;gt; {
                game_state_stack.push(GameStateData::Gameplay(GameplayState::new(&amp;amp;graphics_layer)));
            }

            GameStateType::Pause =&amp;gt; {
                game_state_stack.push(GameStateData::Pause(PauseState::new(&amp;amp;graphics_layer)));
            }
        }

        // make sure to reset the state
        next_game_state = GameStateTransitionState::Unchanged;
    }

    GameStateTransitionState::ReturnToPreviousState =&amp;gt; {
        // remove the top most state from the stack
        game_state_stack.pop();

        // close the game once all game states have been deleted
        if game_state_stack.len() == 0 {
            should_game_close = true;
            continue;
        }

        // make sure to reset the transition state
        next_game_state = GameStateTransitionState::Unchanged;
    }

    GameStateTransitionState::Unchanged =&amp;gt; { }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this, we have the main transition logic in-place and only miss the logic to draw and update the game states.&lt;/p&gt;

&lt;p&gt;Updating is done in reverse order, this allows higher-level states to block input from reaching lower levels.
Each state atm returns if a state transition is required and if the input should be blocked from reaching lower levels.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;for state in game_state_stack.iter_mut().rev() {
    let state_status = match state {
        GameStateData::Gameplay(game_state) =&amp;gt; {
            let (prev_frame_params, frame_params) = if update_frame_number % 2 == 0 {
                (&amp;amp;game_state.frame_data0, &amp;amp;mut game_state.frame_data1)
            } else {
                (&amp;amp;game_state.frame_data1, &amp;amp;mut game_state.frame_data0)
            };

            update_gameplay_state(prev_frame_params, frame_params, &amp;amp;messages, dt)
        }

        GameStateData::Pause(game_state) =&amp;gt; {
            let (prev_frame_params, frame_params) = if update_frame_number % 2 == 0 {
                (&amp;amp;game_state.frame_data0, &amp;amp;mut game_state.frame_data1)
            } else {
                (&amp;amp;game_state.frame_data1, &amp;amp;mut game_state.frame_data0)
            };

            update_pause_state(prev_frame_params, frame_params, &amp;amp;messages, dt)
        }
    };

    if state_status.block_input {
        messages.clear();
    }

    match state_status.transition_state {
        GameStateTransitionState::Unchanged =&amp;gt; {}
        _ =&amp;gt; match next_game_state {
            GameStateTransitionState::Unchanged =&amp;gt; {
                next_game_state = state_status.transition_state;
            }
            _ =&amp;gt; {
                panic!(&amp;quot;logic error, only one state transition per frame is allowed&amp;quot;);
            }
        },
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The drawing follows the same logic, but the drawing order is from back to front.
This allows higher-level states, such as the pause state, to be drawn on top of the lower states.&lt;/p&gt;

&lt;h3 id=&#34;rendering-update&#34;&gt;Rendering Update&lt;/h3&gt;

&lt;p&gt;A few updates on the rendering side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The PSO state has been extended to contain the blend state, this is required so that the pause state can draw a partially transparent overlay&lt;/li&gt;
&lt;li&gt;The grid is using the same shader as before. Drawing a quad for each tile. Good enough for now&lt;/li&gt;
&lt;li&gt;The Window API was updated so that the output size of the Window can be specified when creating the Window&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;Time to focus a little on code structure again.
With all this logic, we are back &amp;gt;600 lines of Rust code in a single file.&lt;/p&gt;

&lt;p&gt;Time to split it into multiple modules across different files.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-12&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 11 - Mouse Input</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-11/</link>
      <pubDate>Wed, 22 Apr 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-11/</guid>
      <description>

&lt;h2 id=&#34;goal&#34;&gt;Goal&lt;/h2&gt;

&lt;p&gt;At the end of this part, we will have the necessary support to receive mouse input in the Game.&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;The task can be split into three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receive Mouse input from Win32&lt;/li&gt;
&lt;li&gt;Convert mouse input into a Rust format and pass this to the Game&lt;/li&gt;
&lt;li&gt;React to the mouse input in the Game code&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;Processing mouse input on Windows is fundamentally quite simple. They use the same windows message loop I am already using to process window messages.&lt;/p&gt;

&lt;p&gt;For Mouse input, I am going to handle these three events: WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP&lt;/p&gt;

&lt;p&gt;Each time the mouse will be moved over the window a WM_MOUSEMOVE is sent.
We unpack the arguments and send them to the game layer for further processing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;if msg == WM_MOUSEMOVE {
    // retrieve the window state
    let window_state_ptr = GetWindowLongPtrW(h_wnd, GWLP_USERDATA) as *mut WindowThreadState;
    let window_state: &amp;amp;mut WindowThreadState = window_state_ptr.as_mut().unwrap();

    // unpack the arguments of the event
    // the position is stored in l_param
    let x = winapi::shared::windowsx::GET_X_LPARAM(l_param);
    let y = winapi::shared::windowsx::GET_Y_LPARAM(l_param);

    // and send a message to the Rust message processor
    window_state
        .message_sender
        .send(WindowMessages::MousePositionChanged(
            MousePositionChangedData { x, y },
        ))
        .unwrap();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The functionality for WM_LBUTTONDOWN and WM_LBUTTONUP is even more straightforward as there are no arguments to unpack, and we only need to send a message.&lt;/p&gt;

&lt;p&gt;To make this all work, we need to extend the WindowMessages enum. I really love the flexibility of Rust enums btw :)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub struct MousePositionChangedData {
    pub x: i32,
    pub y: i32,
}

pub enum WindowMessages {
    // mouse related messages
    MousePositionChanged(MousePositionChangedData),
    MouseLeftButtonDown,
    MouseLeftButtonUp,

    // window related messages
    WindowCreated(WindowCreatedData),
    WindowClosed,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this functionalliy added we will be greeted with a new compiler error:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error[E0004]: non-exhaustive patterns: `MousePositionChanged(_)`, `MouseLeftButtonDown` and `MouseLeftButtonUp` not covered
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All enum handling by default needs to be exhaustive. Meaning all possible cases need to be handled.&lt;/p&gt;

&lt;p&gt;This is really useful as each time a new enum is added, the compiler will emit an error until we investigated each use case of the events.&lt;/p&gt;

&lt;p&gt;For now, I will just print the information to the console. Responding to the input will be done in a later part.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt; match x {
    WindowMessages::MousePositionChanged(pos) =&amp;gt; {
        println!(&amp;quot;cursor position changed: x {0}, y {1}&amp;quot;, pos.x, pos.y);
    }

    WindowMessages::MouseLeftButtonDown =&amp;gt; {
        println!(&amp;quot;mouse:left down&amp;quot;);
    }

    WindowMessages::MouseLeftButtonUp =&amp;gt; {
        println!(&amp;quot;mouse:left up&amp;quot;);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is all we need to implement input processing. Well, there is one more small part to deal with.
Testing the application like this, we will notice an issue.&lt;/p&gt;

&lt;p&gt;Messages are only sent while the mouse is hovering over the window, and that can be a problem.&lt;/p&gt;

&lt;p&gt;For example, if the user presses the left mouse button while insider the window, moves the mouse out of the window and releases the mouse.
We will never receive a WM_LBUTTONUP event, and the Game might think the mouse button is still pressed.&lt;/p&gt;

&lt;p&gt;To deal with this, I am extending the messages with two more cases: MouseFocusGained and MouseFocusLost
When the mouse is moved outside of the window, I will send a MouseFocusLost to the Game, and the Game can react to it appropriatly.&lt;/p&gt;

&lt;p&gt;To enable this, I will be using the win32 function &lt;a href=&#34;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-trackmouseevent&#34; target=&#34;_blank&#34;&gt;TrackMouseEvent&lt;/a&gt;
The following code needs to be added to the WM_MOUSEMOVE event. Telling windows, we would like to receive additional mouse tracking events.&lt;/p&gt;

&lt;p&gt;Additionally, I am also sending a MouseFocusGained to make the API symmetrical with  MouseFocusLost&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;if !window_state.is_tracking {
    let mut tme = TRACKMOUSEEVENT {
        dwFlags: TME_LEAVE,
        hwndTrack: h_wnd,
        dwHoverTime: 0,
        cbSize: core::mem::size_of::&amp;lt;TRACKMOUSEEVENT&amp;gt;() as u32,
    };

    TrackMouseEvent(&amp;amp;mut tme);

    window_state.is_tracking = true;

    window_state
        .message_sender
        .send(WindowMessages::MouseFocusGained)
        .unwrap();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;if msg == WM_MOUSELEAVE {
    let window_state_ptr = GetWindowLongPtrW(h_wnd, GWLP_USERDATA) as *mut WindowThreadState;
    let window_state: &amp;amp;mut WindowThreadState = window_state_ptr.as_mut().unwrap();

    if window_state.is_tracking {
        window_state.is_tracking = false;

        window_state
            .message_sender
            .send(WindowMessages::MouseFocusLost)
            .unwrap();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, the two new events will need to be added to the WindowMessages enum. Rust will thankfully throw an error again, and we can update the appropriate receiver logic in the Game.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s it, we receive the necessary mouse input information in the Game.&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;Next time I will connect these individual features into a first small prototype.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-10&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 10 - API cleanup and resource lifetime management</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-10/</link>
      <pubDate>Wed, 15 Apr 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-10/</guid>
      <description>

&lt;p&gt;After last week&amp;rsquo;s post, the code is split into multiple crates, but the game code is still full of direct D3D11 functionality that requires unsafe code.&lt;/p&gt;

&lt;p&gt;I would like the game code to be free of unsafe code. Unsafe code is required, but it should be hidden from the game in the abstraction layers.&lt;/p&gt;

&lt;h2 id=&#34;main-api-components&#34;&gt;Main API components&lt;/h2&gt;

&lt;p&gt;After a cleanup pass of the API, only a few concepts are left.
I am following a very simplified D3D12 design.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GraphicsDeviceLayer

&lt;ul&gt;
&lt;li&gt;Handles d3d11 creation, resources, and swap chain related functionality&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Constant Buffer

&lt;ul&gt;
&lt;li&gt;buffer creation and allocator&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Pipeline State Object

&lt;ul&gt;
&lt;li&gt;groups vertex/pixel shader. This will later be extended to hold other required state&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Render Pass

&lt;ul&gt;
&lt;li&gt;bind render targets and handles color/depth clear&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Command Lists

&lt;ul&gt;
&lt;li&gt;contains all rendering related functionality&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The implementation of this is relatively straight forward. Most Rust structs are mostly wrapper objects around the native D3D11 objects at this point.&lt;/p&gt;

&lt;p&gt;The API example is below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let mut graphics_layer: GraphicsDeviceLayer =
    create_device_graphics_layer(main_window.hwnd, args.enable_debug_device).unwrap();

let pso_desc = PipelineStateObjectDesc {
    shader_name: &amp;quot;target_data/shaders/screen_space_quad&amp;quot;,
};

let screenspace_quad_pso: PipelineStateObject = create_pso(&amp;amp;graphics_layer.device, pso_desc);

begin_render_pass(
    &amp;amp;mut graphics_layer.graphics_command_list,
    color,
    &amp;amp;graphics_layer.backbuffer_rtv,
);

let obj1_alloc = HeapAlloc::new(
    ScreenSpaceQuadData {
        color,
        padding: 0.0,
        scale: Float2 { x: 0.5, y: 0.5 },
        position: Float2 { x: 0.0, y: 0.0 },
    },
    &amp;amp;gpu_heap.gpu_data,
    &amp;amp;mut gpu_heap.state,
);

bind_pso(
    &amp;amp;mut graphics_layer.graphics_command_list,
    &amp;amp;screenspace_quad_pso,
);

bind_constant(&amp;amp;mut graphics_layer.graphics_command_list, 0, &amp;amp;obj1_alloc);

draw_vertices(&amp;amp;mut graphics_layer.graphics_command_list, 4);

unmap_gpu_buffer(gpu_heap.gpu_data, &amp;amp;graphics_layer);

execute_command_list(&amp;amp;graphics_layer, &amp;amp;graphics_layer.graphics_command_list);

present_swapchain(&amp;amp;graphics_layer);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The more interesting parts from a Rust perspective is the way to handle D3D11 resource management.&lt;/p&gt;

&lt;h2 id=&#34;d3d11-memory-management&#34;&gt;D3D11 memory management&lt;/h2&gt;

&lt;p&gt;In D3D11, each object is reference counted, and resources are only released once the reference count reaches 0.  Each object implements the IUnknown interface that provides the necessary functionality.&lt;/p&gt;

&lt;p&gt;D3D11 will internally increment ref counts, but it&amp;rsquo;s the developers&amp;rsquo; responsibility to release these.&lt;/p&gt;

&lt;p&gt;In Rust, generally, all resources are released once they reach the end of their lifetime.
And I would like to keep these semantics for my API.&lt;/p&gt;

&lt;p&gt;This can be achieved through the implementation of the &lt;a href=&#34;https://doc.rust-lang.org/std/ops/trait.Drop.html&#34; target=&#34;_blank&#34;&gt;Drop trait&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&#34;drop-trait&#34;&gt;Drop Trait&lt;/h3&gt;

&lt;p&gt;A &lt;a href=&#34;https://doc.rust-lang.org/1.8.0/book/traits.html&#34; target=&#34;_blank&#34;&gt;trait object&lt;/a&gt; defines the notion of an Interface.
It allows us to express what types of functionality are supported by a type.&lt;/p&gt;

&lt;p&gt;This can be used for static dispatching for the use in generics/templates (in C++) or dynamic dispatching.&lt;/p&gt;

&lt;p&gt;A struct can implement any number of traits. Some, like the drop trait, are provided by the compiler unless we specify a customized implementation.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s what we are doing for our wrapper types to enable the D3D resources to be released in a way that matches Rust semantics.&lt;/p&gt;

&lt;p&gt;The core type of the graphics layer is the GraphicsDeviceLayer struct. The implementation looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub struct GraphicsDeviceLayer&amp;lt;&#39;a&amp;gt; {
    pub immediate_context: *mut ID3D11DeviceContext,
    pub swapchain: *mut IDXGISwapChain1,
    pub backbuffer_texture: *mut ID3D11Texture2D,

    pub backbuffer_rtv: RenderTargetView&amp;lt;&#39;a&amp;gt;,
    pub graphics_command_list: GraphicsCommandList&amp;lt;&#39;a&amp;gt;,

    pub device: GraphicsDevice&amp;lt;&#39;a&amp;gt;,
}

impl Drop for GraphicsDeviceLayer&amp;lt;&#39;_&amp;gt; {
    fn drop(&amp;amp;mut self) {
        unsafe {
            leak_check_release( self.backbuffer_texture.as_ref().unwrap(), 0, self.device.debug_device);
            leak_check_release( self.immediate_context.as_ref().unwrap(), 0, self.device.debug_device);
            leak_check_release( self.swapchain.as_ref().unwrap(), 0, self.device.debug_device);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see that the &lt;code&gt;impl Drop&lt;/code&gt; only contains the explicit release logic for the native D3D11 objects stored as part of the object itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;leak_check_release&lt;/code&gt; will assert if the reference count has not reached 0 and print additional information using the D3D11 debug device if available.&lt;/p&gt;

&lt;p&gt;All other objects are Rust types, and I implemented the Drop trait for all of them. They are responsible for deleting the objects they contain.&lt;/p&gt;

&lt;p&gt;The order in which drop is called might be surprising.&lt;/p&gt;

&lt;p&gt;First, the drop function for the root object is called.
At the end of the root drop functions, all drop functions of the child items are called.
This is done in the order in which they are defined in the struct.&lt;/p&gt;

&lt;p&gt;If those objects have children themselves, those will be called before moving on to the next item in the parent struct.&lt;/p&gt;

&lt;p&gt;For this class structure it will be in this order:&lt;/p&gt;

&lt;p&gt;GraphicsDeviceLayer &amp;gt; RenderTargetView &amp;gt;
GraphicsCommandList &amp;gt; (possible child types) &amp;gt; GraphicsDevice&lt;/p&gt;

&lt;p&gt;Implementing the drop trait for all wrapper objects enables us to remove all manual Release calls from the game code.
The borrow checker and the lifetime specifiers make sure that all objects will be released in the correct order.&lt;/p&gt;

&lt;p&gt;Externally owned objects will be released first. For example, Constant Buffer. The lifetime specifier defines that the references are not allowed to outlive the GraphicsDeviceLayer. Therefore the object has to be dropped before dropping the GraphicsDeviceLayer.&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;With this work completed, we have a foundation to build upon.
And it&amp;rsquo;s time to start implementing a first gameplay prototype.
What&amp;rsquo;s missing for that?&lt;/p&gt;

&lt;p&gt;Drawing multiple quads and input handling. I will be looking at these topics next.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-10&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 9 - Rust compilation structure</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-9/</link>
      <pubDate>Mon, 06 Apr 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-9/</guid>
      <description>

&lt;p&gt;The project structure is often neglected when starting on a new project, especially for small projects, but I feel it&amp;rsquo;s essential.
Rust provides two main building blocks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crate&lt;/li&gt;
&lt;li&gt;Module&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A Crate is the highest level, and each Crate contains one or more modules.
The details are well explained in the &lt;a href=&#34;https://doc.rust-lang.org/1.24.1/book/first-edition/crates-and-modules.html&#34; target=&#34;_blank&#34;&gt;Rust Book&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the current state of the game code, we have a few logical blocks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Game code&lt;/li&gt;
&lt;li&gt;Window creation logic&lt;/li&gt;
&lt;li&gt;Graphics foundation layer&lt;/li&gt;
&lt;li&gt;Memory management&lt;/li&gt;
&lt;li&gt;Shader interface&lt;/li&gt;
&lt;li&gt;A few extensions to the Rust standard library&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first idea might be to keep everything inside a single &lt;code&gt;rustmatch3&lt;/code&gt; Crate and move the other functionality into modules.
This is what I would do for a C++ project of this complexity.&lt;/p&gt;

&lt;p&gt;In Rust, I am going to follow a different design and split this code into multiple Crates.
The reason for this is the difference in the compilation unit size between Rust and C++.&lt;/p&gt;

&lt;p&gt;In C++ each .cpp file is a compilation unit.
In Rust, the compilation unit is a Crate.&lt;/p&gt;

&lt;p&gt;The compiler is invoked once for each compilation unit.
Therefore scaling to multiple cores is trivial for C++ as there are typically more files then there are cores.&lt;/p&gt;

&lt;p&gt;The Rust compiler (Rustc) will only be invoked once per Crate.
Therefore scaling to multiple cores for a single crate can only be achieved through multithreading within the compiler itself.&lt;/p&gt;

&lt;p&gt;To understand how good the Rustc compiler is at using available CPU resources, I ran some tests.&lt;/p&gt;

&lt;h2 id=&#34;rust-compilation-test-case-image-rescaler&#34;&gt;Rust Compilation - Test Case - Image Rescaler&lt;/h2&gt;

&lt;p&gt;The following example is taken from one of my smaller Rust based tools.
It is a simple tool that rescales images to a resolution suited for publishing on the web.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-9/system_saturation_crates.png&#34; alt=&#34;Image rescaler compilation timeline&#34; title=&#34;Image rescaler compilation timeline&#34; /&gt;&lt;/p&gt;

&lt;p&gt;The upper half of this capture shows a timeline of which crates are being compiled. The lower half shows the status of the compilation units and the CPU usage over time.&lt;/p&gt;

&lt;p&gt;From these graphs, we can see that the system is fully saturated at the start. Not surprising as the number of active units is always at the maximum value for my machine.&lt;/p&gt;

&lt;p&gt;As the number of active units drops, however, so does the system utilization.&lt;/p&gt;

&lt;p&gt;Especially insightful is the image crate.
It takes around 16s to compile. Out of these, 7 seconds are spent on phase 1 of the compilation, and the rest is spent on phase 2.&lt;/p&gt;

&lt;p&gt;The Rust compilation is split into two high-level phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phase 1: generates metadata (list of types, dependencies, exports)&lt;/li&gt;
&lt;li&gt;Phase 2: code generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As can be seen from the CPU usage, phase 1 is unable to thoroughly saturate my system.
Phase 2, on the other hand, can use my systems resources a lot better.&lt;/p&gt;

&lt;p&gt;(the full graph can be found &lt;a href=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-9/cargo-timing-img_rescaler.html&#34;&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;h2 id=&#34;rust-compilation-test-case-rustc&#34;&gt;Rust Compilation - Test Case - Rustc&lt;/h2&gt;

&lt;p&gt;The same behavior can be found in the rustc compiler itself. The capture was published in &lt;a href=&#34;https://blog.mozilla.org/nnethercote/2019/10/10/visualizing-rust-compilation/&#34; target=&#34;_blank&#34;&gt;Visualizing Rust compilation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-9/rustc_compilation.png&#34; alt=&#34;Rustc compilation timeline&#34; title=&#34;Rustc compilation timeline&#34; /&gt;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a very extreme example as there are more than 20 seconds of compilation where the CPU is pretty much idle!
This is caused because the dependent Creates are only able to start compiling after the completion of phase 1.&lt;/p&gt;

&lt;h2 id=&#34;crate-heavy-architecture&#34;&gt;Crate heavy architecture&lt;/h2&gt;

&lt;p&gt;Therefore I am suggesting to prefer a project structure that leans more towards crates with a shallow tree of dependencies.
Having dependencies in the middle of the dependency chain can introduce large bubbles, as can be seen in Rustc&lt;/p&gt;

&lt;p&gt;The aim should be to allow as many crates as possible to be compiled independently.&lt;/p&gt;

&lt;p&gt;Should each file be a separate crate, mimicking the C++ compilation model?
No, I don&amp;rsquo;t think so. There is an overhead to each Crate. There has to be a balance.&lt;/p&gt;

&lt;p&gt;The best way is to keep checking the timings to detect if a single crate is starting to become a bottleneck.
Once this happens, it&amp;rsquo;s time to start splitting a single Crate into multiple Crates.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://blog.mozilla.org/nnethercote/2019/10/10/visualizing-rust-compilation/&#34; target=&#34;_blank&#34;&gt;Visualizing Rust compilation&lt;/a&gt; explains the necessary commands. Sadly these are only available on nightly :(&lt;/p&gt;

&lt;h3 id=&#34;game-structure&#34;&gt;Game structure&lt;/h3&gt;

&lt;p&gt;So given all this information, how did I structure this project?
For now, I split it into 3 creates&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Window Creation&lt;/li&gt;
&lt;li&gt;Graphics foundation layer + Memory management&lt;/li&gt;
&lt;li&gt;Game + Shader interface&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is a timing capture of a full rebuild:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-9/game_compilation.png&#34; alt=&#34;Rust Match3 compilation&#34; title=&#34;Rust Match3 compilation&#34; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see most time is actually spend generation the native wrapper to call into Win32 API (Winapi crate)
Sadly both the graphics and window creation require Winapi. Is it really needed to take 6 seconds in phase 1 to compile a win32 wrapper? Probably not.&lt;/p&gt;

&lt;p&gt;Doing a minimal build with only changes to the game code takes 0.4 seconds.
That is good to enough for now :)&lt;/p&gt;

&lt;h2 id=&#34;next-part&#34;&gt;Next Part&lt;/h2&gt;

&lt;p&gt;In the next part, I will be doing some graphics code again. Time to clean up the rendering interface so that the game doesn&amp;rsquo;t have to use any unsafe code, and all interactions with D3D11 are hidden inside the Graphics foundation layer.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-9&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 8 - Using Visual Studio</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-8/</link>
      <pubDate>Tue, 24 Mar 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-8/</guid>
      <description>

&lt;p&gt;There are articles on how to use Visual Studio Code with Rust already, but I prefer to use Visual Studio.&lt;/p&gt;

&lt;p&gt;This article presents my setup on how to use Visual Studio with Rust.
It&amp;rsquo;s not a perfect setup, but it is good enough for me.&lt;/p&gt;

&lt;h2 id=&#34;extension&#34;&gt;Extension&lt;/h2&gt;

&lt;p&gt;There exists a Visual Studio &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=dos-cafe.Rust&#34; target=&#34;_blank&#34;&gt;extension for Rust&lt;/a&gt;.
I have it installed, but mostly using it to get syntax highlighting, it&amp;rsquo;s not essential to use it.&lt;/p&gt;

&lt;h2 id=&#34;project-setup&#34;&gt;Project Setup&lt;/h2&gt;

&lt;p&gt;To use Rust with Visual Studio, I am using a Makefile Project.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/NewProject.png&#34; alt=&#34;Visual Studio makefile project&#34; title=&#34;Visual Studio makefile project&#34; /&gt;&lt;/p&gt;

&lt;p&gt;After creating the project, my first step is to delete the Win32 configuration. Since I am not interested in developing x86 applications. Other platforms could be added as required.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/DeleteWin32.png&#34; alt=&#34;Delete Win32 configuration&#34; title=&#34;Delete Win32 configuration&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Next I create a few extra configurations:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/Configurations.png&#34; alt=&#34;Extra configurations&#34; title=&#34;Extra configurations&#34; /&gt;&lt;/p&gt;

&lt;p&gt;The names should be mostly self-explanatory what the purposes are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run Clippy&lt;/li&gt;
&lt;li&gt;Build the game&lt;/li&gt;
&lt;li&gt;Run unit tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These configurations allow the common operation to be accessed right from within Visual Studio.
Configuration management is mostly done with property sheets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/PropertyManagement.png&#34; alt=&#34;Property Sheets&#34; title=&#34;Property Sheets&#34; /&gt;&lt;/p&gt;

&lt;p&gt;RustBase provides the default settings, such as OutputDirectory and IntermidiateDirectory.
And the more specific property sheets provide the necessary Cargo commands to be executed via nmake.&lt;/p&gt;

&lt;p&gt;With all the setup, I am now able to compile the game, debug the game using the Visual Studio debugger, run Clippy as well as Unit Tests.&lt;/p&gt;

&lt;h2 id=&#34;debug-unit-test-executables&#34;&gt;Debug Unit Test executables&lt;/h2&gt;

&lt;p&gt;Debugging Unit Tests is a bit more tricky because Cargo doesn&amp;rsquo;t generate deterministic file names for Unit Test executables.
There is an open &lt;a href=&#34;https://github.com/rust-lang/Cargo/issues/1924&#34; target=&#34;_blank&#34;&gt;issue&lt;/a&gt; for it. It doesn&amp;rsquo;t seem to have gained much traction, though.&lt;/p&gt;

&lt;p&gt;The solution that I am using is very primitive. When the Unit Tests are compiled, it will print the name of the generated executable. I then manually copy this name into the debug command.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/UnitTestDebug.png&#34; alt=&#34;Debug UnitTest&#34; title=&#34;Debug UnitTest&#34; /&gt;&lt;/p&gt;

&lt;p&gt;This name seems to be deterministic for the same version of Rust, but after a version update, the name changes, and I need to copy it again. Not a great solution, but it works.&lt;/p&gt;

&lt;p&gt;If you know a better way, please let me know :)&lt;/p&gt;

&lt;h3 id=&#34;rustfmt-integration&#34;&gt;Rustfmt integration&lt;/h3&gt;

&lt;p&gt;Cargo formatting is a handy command to have easy access to. I suggest creating an External Tool in Visual Studio to enable one-click access to the tool.&lt;/p&gt;

&lt;p&gt;The setup is shown below
&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/CargoFmt.png&#34; alt=&#34;Cargo fmt integration&#34; title=&#34;Cargo fmt integration&#34; /&gt;&lt;/p&gt;

&lt;p&gt;And with the external tool entry created, it is now accessible from the Tools category. With a single click, the source code will be formatted with the specified guidelines.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/ExternalFmt.png&#34; alt=&#34;External Cargo fmt tool&#34; title=&#34;External Cargo fmt tool&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;rust-debugging-advice&#34;&gt;Rust Debugging Advice&lt;/h2&gt;

&lt;p&gt;A few extra recommendations to make your Rust debugging experience better.&lt;/p&gt;

&lt;h3 id=&#34;debug-panics&#34;&gt;Debug Panics&lt;/h3&gt;

&lt;p&gt;Rust panics will generally try to unwind the stack or abort the application execution.
But when a debugger is attached, I generally want to halt the debugger at the point when a panic occurs to inspect the program state.&lt;/p&gt;

&lt;p&gt;Rust provides the possibility to do this, but it&amp;rsquo;s not very well documented.
The rust panic handler is internally always calling the unmangled function &lt;code&gt;rust_panic&lt;/code&gt;, that also never gets inlined.&lt;/p&gt;

&lt;p&gt;It is possible to set a function breakpoint on this function.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/RustPanicDebug.png&#34; alt=&#34;Rust Panic Breakpoint&#34; title=&#34;Rust Panic Breakpoint&#34; /&gt;&lt;/p&gt;

&lt;p&gt;With this breakpoint set each time a panic occurs, you will get a breakpoint in the debugger.&lt;/p&gt;

&lt;p&gt;The function is sadly only called with a deep call stack. We will need to go a few levels up the stack until you find the user code.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/PanicDebugCallstack.png&#34; alt=&#34;Panic Callstack&#34; title=&#34;Panic Callstack&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;rust-source-code&#34;&gt;Rust source code&lt;/h3&gt;

&lt;p&gt;As you might notice in the previous screenshot, I have symbols as well as source code for the Rust implementation itself.
When you hit the panic breakpoint from Visual Studio the first time, it will not be able to resolve symbols but instead, ask for the source code location.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-part-8/AskingForSource.png&#34; alt=&#34;Delete Win32&#34; title=&#34;Delete Win32&#34; /&gt;&lt;/p&gt;

&lt;p&gt;The Rust installations ships with full source code.
It can be found in the rustup installation folder, for me it&amp;rsquo;s located in this location:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;C:\Users\jendr\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pointing Visual Studio at the correct location will resolve the symbols and show you the Rust code for the position.
It also will allow you to step through the Rust implementations. Really useful to learn about how Rust library functionality is internally implemented.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s it for today.&lt;/p&gt;

&lt;p&gt;Next time I m going to improve the Rust code organization a little bit before continuing the programming of the game.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-8&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 7 - Rust lifetimes and GPU Constant Allocator</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-7/</link>
      <pubDate>Wed, 11 Mar 2020 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-7/</guid>
      <description>

&lt;p&gt;In this part, I will be talking about how to write a custom memory allocator using Rust and D3D11.
The concepts are applicable for general-purpose memory allocations but designed for the requirements of constant buffer management.&lt;/p&gt;

&lt;p&gt;I am going to try to explain Rust lifetimes in the process and show how it can help to eliminate some classes of bugs.&lt;/p&gt;

&lt;h1 id=&#34;constant-buffer-overview&#34;&gt;Constant Buffer Overview&lt;/h1&gt;

&lt;p&gt;There are different ways to approach constant buffer management, I will implement it as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allocate one large constant buffer for each frame&lt;/li&gt;
&lt;li&gt;Define a linear bump allocator that uses this buffer as backing storage&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&#34;https://docs.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-pssetconstantbuffers1&#34; target=&#34;_blank&#34;&gt;PSSetConstantBuffers1&lt;/a&gt; to record the offset into this buffer for each draw call&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&#34;extend-the-screen-space-quad&#34;&gt;Extend the screen space quad&lt;/h1&gt;

&lt;p&gt;Before we can start looking at the memory management, we need to update the shader so that constant data is used.
The updated shader below allows the size, position, and final quad-color to be read from the constant buffer.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-hlsl&#34;&gt;cbuffer ScreenSpaceQuadData : register(b0)
{
    float3 color;
    float2 scale;
    float2 position;
};

VertexToPixelShader VS_main(uint vertex_id: SV_VertexID)
{
    VertexToPixelShader output;

    switch (vertex_id) {
    case 0: output.position_clip = float4(-1,  1, 0, 1); break; // top-left
    case 1: output.position_clip = float4( 1,  1, 0, 1); break; // top-right
    case 2: output.position_clip = float4(-1, -1, 0, 1); break; // bottom-left
    case 3: output.position_clip = float4( 1, -1, 0, 1); break; // bottom-right
    }

    output.position_clip.xy *= scale;
    output.position_clip.xy += position;

    return output;
}

float3 PS_main(VertexToPixelShader input) : SV_TARGET
{
    return color;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To interface with this structure from Rust, we need to define a few helper classes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;#[repr(C)]
struct Float3 {
    x: f32,
    y: f32,
    z: f32,
}

#[repr(C)]
struct Float2 {
    x: f32,
    y: f32,
}

#[repr(C)]
struct ScreenSpaceQuadData {
    color: Float3,
    padding: f32,
    scale: Float2,
    position: Float2,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The one thing to call out is &lt;code&gt;repr(C)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This instructs the compiler to follow the C alignment rules. The Rust and C alignment rules are very similar, but the significant difference is that the Rust compiler is free to reorder fields.
At the time of writing, the compiler doesn&amp;rsquo;t seem to be doing that, however.&lt;/p&gt;

&lt;p&gt;One problem is that HLSL doesn&amp;rsquo;t follow the C alignment rules and instead packs on float4 boundaries.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s why you see a &lt;code&gt;padding: f32&lt;/code&gt; inside of the ScreenSpaceQuadData definition.
This is required because following the C alignment rules, &lt;code&gt;scale&lt;/code&gt; would directly follow &lt;code&gt;color&lt;/code&gt;.
To follow the HLSL rules, we need one padding float to fill the float4.&lt;/p&gt;

&lt;p&gt;The following two float2 types are packed into a single float4, so no padding is required for those variables.&lt;/p&gt;

&lt;p&gt;With this, we have a Rust layout that matches the HLSL constant buffer layout.
Time to look at the API result of the constant buffer system, and then I will present the thoughts and reasons behind the design.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let frame_constant_buffer = create_constant_buffer(
    graphics_device_layer.native.device,
    1024 * 8, // size of the buffer
),

let mut gpu_heap = LinearAllocator {
    gpu_data: map_gpu_buffer(buff, graphics_device_layer.native.context),
    state: LinearAllocatorState { used_bytes: 0 },
};

let obj1_alloc: HeapAlloc&amp;lt;ScreenSpaceQuadData&amp;gt; = HeapAlloc::new(
    ScreenSpaceQuadData { color, padding: 0.0,
        scale: Float2 { x: 1.0, y: 1.0 },
        position: Float2 { x: 0.0, y: 0.0 },
    },
    &amp;amp;gpu_heap.gpu_data,
    &amp;amp;mut gpu_heap.state,
);

let first_constant: u32 = obj1_alloc.first_constant_offset;
let num_constants: u32 = obj1_alloc.num_constants;

 command_context1.as_ref().unwrap().PSSetConstantBuffers1(
    0, // which slot to bind to
    1, // the number of buffers to bind
    &amp;amp;frame_data.frame_constant_buffer.native_buffer, // the buffer to bind
    &amp;amp;first_constant, // the first constant offset
    &amp;amp;num_constants, // number of constants to bind
);

command_context.as_ref().unwrap().Draw(4, 0);

unmap_gpu_buffer(gpu_heap.gpu_data, graphics_device_layer.native.context);

&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;implementation&#34;&gt;Implementation&lt;/h1&gt;

&lt;p&gt;The underlying memory is provided from a constant buffer.
This buffer is located in GPU accessible memory and needs to be mapped so that the CPU can access it.&lt;/p&gt;

&lt;p&gt;The function interface looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn map_gpu_buffer&amp;lt;&#39;a&amp;gt;(
    buffer: &amp;amp;&#39;a mut ID3D11Buffer,
    context: &amp;amp;ID3D11DeviceContext,
) -&amp;gt; MappedGpuData&amp;lt;&#39;a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The one thing that will immediately stick out is the use &lt;code&gt;&amp;lt;&#39;a&amp;gt;&lt;/code&gt; and &lt;code&gt;&#39;a&lt;/code&gt; on the types.&lt;/p&gt;

&lt;p&gt;These are lifetime annotations. Every reference in Rust has a lifetime, but in many situations, &lt;a href=&#34;https://doc.rust-lang.org/1.9.0/book/lifetimes.html#lifetime-elision&#34; target=&#34;_blank&#34;&gt;lifetime-elision&lt;/a&gt; makes it possible to omit the annotations. But there are many situations in which the lifetime is unclear and needs to be provided explicitly.&lt;/p&gt;

&lt;p&gt;An Important point to stress, the borrow checker only looks at the function definition for lifetime tracking.
It doesn&amp;rsquo;t inspect the code inside a function.&lt;/p&gt;

&lt;p&gt;In this case, the lifetime annotations can be read as follows:&lt;/p&gt;

&lt;p&gt;The function accepts a reference to an ID3D11Buffer. This buffer object has lifetime &lt;code&gt;&#39;a&lt;/code&gt;.
The function returns a MappedGpuData, which has the same lifetime annotation &lt;code&gt;&#39;a&lt;/code&gt;.
This means that MappedGpuData internally contains a reference to data based on ID3D11Buffer.&lt;/p&gt;

&lt;p&gt;Therefore this requires the return value to have the same or shorter lifetime then the buffer it was derived from.&lt;/p&gt;

&lt;p&gt;The struct needs explicit lifetime annotations to make this visible to the compiler.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub struct MappedGpuData&amp;lt;&#39;a&amp;gt; {
    data: &amp;amp;&#39;a [u8], // reference to slice of cpu accessible gpu memory
    buffer: &amp;amp;&#39;a mut ID3D11Buffer, // reference to the d3d11 buffer the data comes from
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have the building blocks required for the implementation of &lt;code&gt;map_gpu_buffer&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn map_gpu_buffer&amp;lt;&#39;a&amp;gt;(
    buffer: &amp;amp;&#39;a mut ID3D11Buffer,
    context: &amp;amp;ID3D11DeviceContext,
) -&amp;gt; MappedGpuData&amp;lt;&#39;a&amp;gt; {
    let mut mapped_resource = D3D11_MAPPED_SUBRESOURCE {
        pData: std::ptr::null_mut(),
        RowPitch: 0,
        DepthPitch: 0,
    };

    // map the buffer
    let result: HRESULT = unsafe {
        context.Map(
            buffer as *mut ID3D11Buffer as *mut winapi::um::d3d11::ID3D11Resource,
            0, D3D11_MAP_WRITE_NO_OVERWRITE, 0,
            &amp;amp;mut mapped_resource,
        )
    };

    MappedGpuData {
        data: unsafe {
            std::slice::from_raw_parts_mut(
                mapped_resource.pData as *mut u8,
                mapped_resource.RowPitch as usize,
            )
        },
        buffer,
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most of these are just D3D11 function calls, but the construction of the MappedGpuData requires a bit of description.
The structure contains a slice to CPU accessible GPU memory. D3D11 provides us with a pointer and a size, we can combine this information using the unsafe &lt;code&gt;from_raw_parts_mut&lt;/code&gt; to build a slice which can be used as a &amp;ldquo;normal&amp;rdquo; rust slice afterward.&lt;/p&gt;

&lt;p&gt;The mutability of the borrow is forwarded to the returned type. This is independent of how the struct is defined.
Since the buffer is a mutable borrow also the returned MappedGpuData will be a mutable borrow.
This means we cannot map the same buffer twice unless we release the returned borrow.&lt;/p&gt;

&lt;p&gt;Unmapping the buffer is quite straightforward. No lifetime annotations are required as MappedGpuData is passed in by moving ownership. This means after &lt;code&gt;unmap_gpu_buffer&lt;/code&gt; returns, the &lt;code&gt;mapped_data&lt;/code&gt; will not be valid anymore and cannot be accessed.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn unmap_gpu_buffer(mapped_data: MappedGpuData, context: &amp;amp;ID3D11DeviceContext) {
    unsafe {
        context.Unmap(
            mapped_data.buffer as *mut ID3D11Buffer as *mut winapi::um::d3d11::ID3D11Resource,
            0,
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this functionality in place, we are now able to map and unmap GPU constant memory.&lt;/p&gt;

&lt;p&gt;Time to implement an allocator that uses this memory buffer as backing storage.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub struct LinearAllocatorState {
    used_bytes: usize,
}

pub struct LinearAllocator&amp;lt;&#39;a&amp;gt; {
    gpu_data: MappedGpuData&amp;lt;&#39;a&amp;gt;,
    state: LinearAllocatorState,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The allocator is a simple linear allocator called LinearAllocator.
Here the state is split into two separate structs to separate mutable and immutable state.&lt;/p&gt;

&lt;p&gt;Why this split? It&amp;rsquo;s related to the forwarding of borrow mutability. Let us look at how it&amp;rsquo;s used:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let obj1_alloc: HeapAlloc&amp;lt;ScreenSpaceQuadData&amp;gt; = HeapAlloc::new(
    ScreenSpaceQuadData { color, padding: 0.0,
        scale: Float2 { x: 1.0, y: 1.0 },
        position: Float2 { x: 0.0, y: 0.0 },
    },
    &amp;amp;gpu_heap.gpu_data,
    &amp;amp;mut gpu_heap.state,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation of this look as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;pub struct HeapAlloc&amp;lt;&#39;a, T&amp;gt; {
    ptr: &amp;amp;&#39;a mut T,
    first_constant_offset: u32,
    num_constants: u32,
}

impl&amp;lt;&#39;a, T&amp;gt; HeapAlloc&amp;lt;&#39;a, T&amp;gt; {
    pub fn new(
        x: T,
        gpu_data: &amp;amp;&#39;a MappedGpuData,
        state: &amp;amp;mut LinearAllocatorState,
    ) -&amp;gt; HeapAlloc&amp;lt;&#39;a, T&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;HeapAlloc is following the design of &lt;a href=&#34;https://doc.rust-lang.org/std/boxed/struct.Box.html&#34; target=&#34;_blank&#34;&gt;Box&lt;/a&gt; but adjusted for the requirements of D3D11 constant buffer binding.
It contains a mutable borrow of generic Type T with an explicit lifetime annotation.&lt;/p&gt;

&lt;p&gt;The HeapAlloc::new function has an explicit lifetime annotation too, and the return type lifetime matches the lifetime of the MappedGpuData passed into the function.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, the borrow type is forwarded to the reference. Since we want multiple allocations to be done into the same buffer, we cannot use a mutable reference. Otherwise, a second allocation would also return a mutable reference.
But only a single mutable borrow is allowed to be active at the same time.&lt;/p&gt;

&lt;p&gt;We still need to modify the state of the LinearAllocator to increment the allocation offset. Therefore we split the state from the buffer and pass the LinearAllocatorState as mutable borrow.&lt;/p&gt;

&lt;p&gt;The full implementation is below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;impl&amp;lt;&#39;a, T&amp;gt; HeapAlloc&amp;lt;&#39;a, T&amp;gt; {
    pub fn new(
        x: T,
        gpu_data: &amp;amp;&#39;a MappedGpuData,
        state: &amp;amp;mut LinearAllocatorState,
    ) -&amp;gt; HeapAlloc&amp;lt;&#39;a, T&amp;gt; {
        let allocation_size: usize = round_up_to_multiple(std::mem::size_of::&amp;lt;T&amp;gt;(), 256);

        let data_slice = gpu_data.data;
        let start_offset_in_bytes = state.used_bytes;

        let data_ptr =
            data_slice[state.used_bytes..(state.used_bytes + allocation_size)].as_ptr() as *mut T;

        state.used_bytes += allocation_size;

        unsafe {
            // write data into target destination
            std::ptr::write(data_ptr, x);

            HeapAlloc {
                ptr: data_ptr.as_mut().unwrap(),
                first_constant_offset: (start_offset_in_bytes / 16) as u32,
                num_constants: (allocation_size / 16) as u32,
            }
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The core of the alloc construction is based on slices.
The allocator uses the base slice for data and sub-divides this slice into smaller sub-slices.
This operation internally performs range checks to validate that constant allocations don&amp;rsquo;t overflow the source buffer and will cause a Panic if an overflow would be happening.&lt;/p&gt;

&lt;p&gt;With all these pieces in place, we have a working allocator system for constants.&lt;/p&gt;

&lt;p&gt;If you would like to use a HeapAlloc&lt;T&gt; to read/write values, the following traits need to be implemented too:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;impl&amp;lt;T&amp;gt; std::ops::Deref for HeapAlloc&amp;lt;&#39;_, T&amp;gt; {
    type Target = T;

    fn deref(&amp;amp;self) -&amp;gt; &amp;amp;T {
        self.ptr
    }
}

impl&amp;lt;T&amp;gt; std::ops::DerefMut for HeapAlloc&amp;lt;&#39;_, T&amp;gt; {
    fn deref_mut(&amp;amp;mut self) -&amp;gt; &amp;amp;mut T {
        self.ptr
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A few D3D11behaviour worth mentioning related to PSSetConstantBuffers1:&lt;/p&gt;

&lt;p&gt;First of all, this doesn&amp;rsquo;t work on Windows 7 and requires extended interface access (&lt;a href=&#34;https://docs.microsoft.com/en-us/windows/win32/api/d3d11_1/nn-d3d11_1-id3d11devicecontext1&#34; target=&#34;_blank&#34;&gt;ID3D11DeviceContext1&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;To get to the extented interface query it afer creating the base interface:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;command_context.as_ref().unwrap().QueryInterface(
    &amp;amp;ID3D11DeviceContext1::uuidof(),
    &amp;amp;mut command_context1 as *mut *mut ID3D11DeviceContext1
        as *mut *mut winapi::ctypes::c_void,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Additionally, Cargo.toml will need to be adjusted to list d3d11_1&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-toml&#34;&gt;winapi = { version = &amp;quot;0.3&amp;quot;, features = [&amp;quot;winuser&amp;quot;, &amp;quot;d3d11&amp;quot;, &amp;quot;d3d11_1&amp;quot;, &amp;quot;winerror&amp;quot;, &amp;quot;dxgi1_2&amp;quot;] }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is also a bug when this feature is not supported by the driver, as described in &lt;a href=&#34;https://docs.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-pssetconstantbuffers1#calling-pssetconstantbuffers1-with-command-list-emulation&#34; target=&#34;_blank&#34;&gt;MSDN - Calling PSSetConstantBuffers1 with command list emulation&lt;/a&gt; but a workaround is provided.&lt;/p&gt;

&lt;p&gt;TLDR when runtime emulation doesn&amp;rsquo;t always update the offsets, need to first unbind constant buffers explicitly :(&lt;/p&gt;

&lt;p&gt;The full implementation is on GitHub, and the previously constant color quad is now animated with a cyclic color change between Red and Black.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/red_black_quad.gif&#34; alt=&#34;Quad changing color on blue background&#34; title=&#34;Quad changing color on a blue background&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Please let me know if I got something wrong or explained it in an unclear way.&lt;/p&gt;

&lt;p&gt;Before continuing with the game, I am going to provide an overview of how I am using Rust with Visual Studio on Windows in the next post.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-7&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 6 - Drawing a procedural quad</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-6/</link>
      <pubDate>Wed, 11 Dec 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-6/</guid>
      <description>

&lt;p&gt;With a working swap chain, nothing will stop us from rendering a quad.&lt;/p&gt;

&lt;p&gt;We will be looking at the following topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;generating vertex data in a shader&lt;/li&gt;
&lt;li&gt;compile shaders&lt;/li&gt;
&lt;li&gt;load shaders&lt;/li&gt;
&lt;li&gt;record draw commands&lt;/li&gt;
&lt;li&gt;executing command lists&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;procedural-quad-shaders&#34;&gt;procedural quad shaders&lt;/h2&gt;

&lt;p&gt;What is a procedural quad?
This means we don&amp;rsquo;t use any data from vertex buffers, but instead, the system provided SV_VertexID is used to generate the vertex positions inside of the vertex shader itself.&lt;/p&gt;

&lt;p&gt;This makes drawing a quad easier since no buffer needs to created, filled from the CPU, and bound to the pipeline.
The vertex shader is below:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-hlsl&#34;&gt;VertexToPixelShader VS_main(uint vertex_id: SV_VertexID)
{
    VertexToPixelShader output;

    switch (vertex_id) {
    case 0: output.position_clip = float4(-1,  1, 0, 1); break; // top-left
    case 1: output.position_clip = float4( 1,  1, 0, 1); break; // top-right
    case 2: output.position_clip = float4(-1, -1, 0, 1); break; // bottom-left
    case 3: output.position_clip = float4( 1, -1, 0, 1); break; // bottom-right
    }

    output.position_clip.xy *= 0.5f; // change the size of the quad a bit

    return output;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;compile-shader&#34;&gt;compile shader&lt;/h2&gt;

&lt;p&gt;Given a shader, we need to compile it; for now, a batch file is all that is required.
Shaders are compiled using the Microsoft FXC compiler, which gets distributed in the Windows SDK.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bat&#34;&gt;:: compile VS shader
..\build_environment\microsoft\fxc\fxc.exe /T vs_4_0 src_data\shaders\screen_space_quad.hlsl /EVS_main /Fo target_data\shaders\screen_space_quad.vsb
..\build_environment\microsoft\fxc\fxc.exe /T ps_4_0 src_data\shaders\screen_space_quad.hlsl /EPS_main /Fo target_data\shaders\screen_space_quad.psb
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;shader-loading&#34;&gt;shader loading&lt;/h3&gt;

&lt;p&gt;Loading and creation shaders are straightforward from Rust. The std filesystem provides the functionality to load binary files into memory.
With the data loaded into memory, a pointer and length are passed to CreateVertexShader/CreatePixelShader, and the shaders are ready to use afterward&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// load a shader
let vertex_shader_memory = std::fs::read(&amp;quot;target_data/shaders/screen_space_quad.vsb&amp;quot;).unwrap();
let pixel_shader_memory  = std::fs::read(&amp;quot;target_data/shaders/screen_space_quad.psb&amp;quot;).unwrap();

let error: HRESULT = d3d11_device.CreateVertexShader(
    vertex_shader_memory.as_ptr() as *const winapi::ctypes::c_void,
    vertex_shader_memory.len(),
    std::ptr::null_mut(),
    &amp;amp;mut vertex_shader as *mut *mut ID3D11VertexShader,
);

let error: HRESULT = d3d11_device.CreatePixelShader(
    pixel_shader_memory.as_ptr() as *const winapi::ctypes::c_void,
    pixel_shader_memory.len(),
    std::ptr::null_mut(),
    &amp;amp;mut pixel_shader as *mut *mut ID3D11PixelShader,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;record-draw-commands&#34;&gt;record draw commands&lt;/h2&gt;

&lt;p&gt;Normally most D3D11 code would now directly execute its work on the immediate context.
I prefer to use DeferredContext instead.&lt;/p&gt;

&lt;p&gt;A deferred context allows commands to be recorded into a command list that can later be executed using the immediate context.
I prefer this way because it makes more logical sense to me.&lt;/p&gt;

&lt;p&gt;GPU execution from the immediate context is under the control of the driver, and there are no guarantees when work might be executed.
With an explicit command list execution steps, it&amp;rsquo;s apparent when CPU work is being done to record commands compared to when the GPU is allowed to execute those commands.&lt;/p&gt;

&lt;p&gt;To be able to record a command list, a deferred context needs to be created.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let mut command_context: *mut ID3D11DeviceContext = std::ptr::null_mut();
let error = graphics_device.CreateDeferredContext(0, &amp;amp;mut command_context);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Given this context, we can now set up the state for our quad.
The code is very compact, all the work is done in the vertex shader without requiring any buffers or shader resource bindings.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// set viewport for the output render target
command_context.RSSetViewports(1, &amp;amp;viewport);

// bind backbuffer as render target
let rtvs: [*mut winapi::um::d3d11::ID3D11RenderTargetView; 1] = [graphics_layer.backbuffer_rtv];
command_context.OMSetRenderTargets( 1, rtvs.as_ptr(), std::ptr::null_mut() );

// bind the shaders
command_context.VSSetShader(vertex_shader, std::ptr::null_mut(), 0);
command_context.PSSetShader(pixel_shader, std::ptr::null_mut(), 0);

// we are drawing 4 vertices using a triangle strip topology
command_context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
command_context.Draw(4, 0);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This recorded all the commands. And are now waiting to be executed by the GPU.
For this, we need access to the recorded command list and execute it using the immediate context.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let mut command_list: *mut ID3D11CommandList = std::ptr::null_mut();
command_context.FinishCommandList(0, &amp;amp;mut command_list);
immediate_context.ExecuteCommandList(command_list, 1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Given all this, and a pixel shader that writes a yellow color. We get to see this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/yellow_quad.png&#34; alt=&#34;Yellow quad on blue background&#34; title=&#34;Yellow quad on a blue background&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Next, I am going to dive deeper into Rust and use lifetimes to write a custom allocator for safe, constant buffer management.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-6&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 5 - D3D11 Device and Swap Chain creation</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-5/</link>
      <pubDate>Thu, 05 Dec 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-5/</guid>
      <description>

&lt;p&gt;With the  window creation in place, we have the necessary foundation to create a D3D11 device and a Swap Chain.&lt;/p&gt;

&lt;p&gt;To start using it, add the necessary dependencies into Cargo.toml.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;[dependencies]
winapi = { version = &amp;quot;0.3&amp;quot;, features = [&amp;quot;winuser&amp;quot;, &amp;quot;d3d11&amp;quot;, &amp;quot;winerror&amp;quot;, &amp;quot;dxgi1_2&amp;quot;] }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating the swap chain is done in the following steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a D3D11 device&lt;/li&gt;
&lt;li&gt;Get access to the DXGI interface&lt;/li&gt;
&lt;li&gt;Create the swap chain&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&amp;rsquo;s look at each step:&lt;/p&gt;

&lt;h2 id=&#34;create-a-d3d11-device&#34;&gt;Create a D3D11 device&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;unsafe {
    // use default adapter
    let adapter: *mut IDXGIAdapter = std::ptr::null_mut();
    let flags: UINT = 0;

    let feature_levels: D3D_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
    let num_feature_levels: UINT = 1;

    let mut d3d11_device: *mut ID3D11Device = std::ptr::null_mut();
    let mut d3d11_immediate_context: *mut ID3D11DeviceContext = std::ptr::null_mut();

    let result: HRESULT = D3D11CreateDevice(
        adapter,
        D3D_DRIVER_TYPE_HARDWARE,
        std::ptr::null_mut(),
        flags,
        &amp;amp;feature_levels,
        num_feature_levels,
        D3D11_SDK_VERSION,
        &amp;amp;mut d3d11_device,
        std::ptr::null_mut(),
        &amp;amp;mut d3d11_immediate_context,
    );

    assert!(result != winapi::shared::winerror::S_OK, &amp;quot;d3d11 device creation failed&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is really close to what you would write in C++ too. Two things stand out:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let adapter: *mut IDXGIAdapter = std::ptr::null_mut();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pointers need to be defined as mutable and therefore need to be initialized with a mutable null pointer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;D3D11CreateDevice&lt;/code&gt; returns the outputs as an output parameter.&lt;/p&gt;

&lt;p&gt;Therefore we need to provide a pointer to the location where the pointer to the created d3d11_device should be stored.&lt;/p&gt;

&lt;p&gt;In Rust, we can pass in a mutable reference to the &lt;code&gt;*mut ID3D11Device&lt;/code&gt;, and it will do the implicit conversion to a pointer type.&lt;/p&gt;

&lt;h3 id=&#34;get-access-to-the-dxgi-interface&#34;&gt;Get access to the DXGI interface&lt;/h3&gt;

&lt;p&gt;Next, we need to get the underlying DXGI interface that was used internally when the d3d11 device was created.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;let mut dxgi_device: *mut IDXGIDevice = std::ptr::null_mut();

// get dxgi device
let result = d3d11_device.as_ref().unwrap().QueryInterface(
    &amp;amp;IDXGIDevice::uuidof(),
    &amp;amp;mut dxgi_device as *mut *mut IDXGIDevice as *mut *mut winapi::ctypes::c_void,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Relatively little code, but what is that cast?!?&lt;/p&gt;

&lt;p&gt;Looking at the &lt;a href=&#34;https://retep998.github.io/doc/winapi/unknwnbase/struct.IUnknown.html&#34; target=&#34;_blank&#34;&gt;QueryInterface&lt;/a&gt; documentation, the parameter is defined as &lt;code&gt;*mut *mut c_void&lt;/code&gt; and our object is of type &lt;code&gt;*mut IDXGIDevice&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let me break down the cast into its steps:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// taking a mutable reference to dxgi device
let mut_ref: &amp;amp;mut *mut IDXGIDevice = &amp;amp;mut dxgi_device;

// next we need to convert the reference to a pointer
let raw_ptr: *mut *mut IDXGIDevice = mut_ref as *mut *mut IDXGIDevice;

// and the pointer type we can cast to the c_void type required by QueryInterface
let void_cast: *mut *mut winapi::ctypes::c_void = raw_ptr as *mut *mut winapi::ctypes::c_void;

// all steps expressed in a single line :)
&amp;amp;mut dxgi_device as *mut *mut IDXGIDevice as *mut *mut winapi::ctypes::c_void
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Afterward, we apply the same idea a few more times until we have access to the &lt;code&gt;IDXGIFactory2&lt;/code&gt; interface that is required to create the swap chain.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let mut dxgi_adapter: *mut IDXGIAdapter = std::ptr::null_mut();
let result = dxgi_device.as_ref().unwrap().GetAdapter(&amp;amp;mut dxgi_adapter);

let mut dxgi_factory: *mut IDXGIFactory1 = std::ptr::null_mut();

let result = dxgi_adapter
    .as_ref()
    .unwrap()
    .GetParent(&amp;amp;IDXGIFactory1::uuidof(), &amp;amp;mut dxgi_factory as * mut *mut IDXGIFactory1 as * mut * mut winapi::ctypes::c_void  );

let mut dxgi_factory_2: *mut IDXGIFactory2 = std::ptr::null_mut();

let result = dxgi_factory
    .as_ref()
    .unwrap()
    .QueryInterface(&amp;amp;IDXGIFactory2::uuidof(), &amp;amp;mut dxgi_factory_2 as * mut * mut IDXGIFactory2 as * mut *mut winapi::ctypes::c_void );

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With all those interfaces we can finally create the swap chain&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
let sd = DXGI_SWAP_CHAIN_DESC1 {
    Width: 0,
    Height: 0,
    Format: DXGI_FORMAT_R8G8B8A8_UNORM,
    SampleDesc: DXGI_SAMPLE_DESC {
        Count: 1,
        Quality: 0,
    },
    BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
    BufferCount: 2,
    AlphaMode: DXGI_ALPHA_MODE_UNSPECIFIED,
    Flags: 0,
    Scaling: DXGI_SCALING_STRETCH,
    SwapEffect: DXGI_SWAP_EFFECT_DISCARD,
    Stereo: 0,
};

let mut swapchain: *mut IDXGISwapChain1 = std::ptr::null_mut();

let result = dxgi_factory_2.as_ref().unwrap().CreateSwapChainForHwnd(
    d3d11_device as *mut winapi::um::unknwnbase::IUnknown,
    hwnd,
    &amp;amp;sd,
    std::ptr::null_mut(),
    std::ptr::null_mut(),
    &amp;amp;mut swapchain,
);

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are currently missing one piece of fundamental data to be able to create the swap chain, and that&amp;rsquo;s the HWND from the window we want to create the swap chain for.&lt;/p&gt;

&lt;p&gt;We need to make some modifications to get access to this. Firstly the WindowMessages enum needs to be updated.
When the window is created, we need to pass the HWND along.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;struct WindowCreatedData {
    hwnd: HWND,
}

enum WindowMessages {
    WindowCreated(WindowCreatedData),
    WindowClosed,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we adjust the sender location to pass the HWND into the WindowCreated message.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;window_state
    .message_sender
    .send(WindowMessages::WindowCreated(WindowCreatedData {
        hwnd: h_wnd,
    }))
    .unwrap();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When trying to build the code, a new error is encountered now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;std::thread::spawn(move || {
^^^^^^^^^^^^^^^^^^ `*mut winapi::shared::windef::HWND__` cannot be sent between threads safely
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Rust compiler can determine if Rust types can be transferred across thread boundaries safely.
When it determines that it&amp;rsquo;s safe, the &lt;code&gt;std::marker::Send&lt;/code&gt; trait will automatically be implemented by the compiler.&lt;/p&gt;

&lt;p&gt;Because of the way HWND is expressed as pointer type in Winapi, the compiler regards the type as unsafe.
But HWND is not really a pointer, but a pointer sized handle.
Therefore it&amp;rsquo;s still ok to pass it between threads, and the trait can be implemented manually.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unsafe impl std::marker::Send for WindowCreatedData {}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Implementing the trait, we promise to the Rust compiler that passing WindowCreatedData between threads is safe.&lt;/p&gt;

&lt;p&gt;With this, we can send the window handle between threads and create the swap chain.
Once the swap chain is created, &lt;code&gt;Present&lt;/code&gt; can be called from our rendering loop, and we will see the window is cleared to black.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;swapchain.as_ref().unwrap().Present(1, 0);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/black_win32_window.png&#34; alt=&#34;Empty Win32 Window&#34; title=&#34;Empty Win32 Window&#34; /&gt;&lt;/p&gt;

&lt;p&gt;With the successfully created swap chain, we can start looking into actually rendering something next week.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-5&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game Series - Part 4 - removing global state</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-4/</link>
      <pubDate>Sat, 30 Nov 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-4/</guid>
      <description>

&lt;p&gt;The current state of the message loop is below, and the problem left to solve is the global state.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;static mut IS_WINDOW_CLOSED: bool = false;

unsafe extern &amp;quot;system&amp;quot; fn window_proc(
    h_wnd: HWND,
    msg: UINT,
    w_param: WPARAM,
    l_param: LPARAM,
) -&amp;gt; LRESULT {
    if msg == WM_DESTROY {
        IS_WINDOW_CLOSED = true;

        PostQuitMessage(0);
    }

    DefWindowProcW(h_wnd, msg, w_param, l_param)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;IS_WINDOW_CLOSED&lt;/code&gt; is required to communicate between the window proc and the main game loop.
Ideally, I would like to pass an object to the message handler and only rely on that state.&lt;/p&gt;

&lt;p&gt;Luckily Windows provides a method for this. This can be achieved in 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;pass a custom struct into CreateWindowExW&lt;/li&gt;
&lt;li&gt;when WM_CREATE is received, store this custom struct into the window user data&lt;/li&gt;
&lt;li&gt;obtain the custom user data in the window handler&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following struct will be used:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;struct WindowThreadState {
    message_sender: std::sync::mpsc::Sender&amp;lt;WindowMessages&amp;gt;,
    is_window_closed : bool
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This struct can be created as usual and passed into CreateWindowExW as the last parameter.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let mut window_state = WindowThreadState { 
            message_sender : channel_sender, 
            is_window_closed : true 
            };

let h_wnd_window = CreateWindowExW(
                ...
                &amp;amp; mut window_state as * mut WindowThreadState as * mut winapi::ctypes::c_void,
            );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pretty simple besides the cast, let me break that one down&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    // taking a mutable reference
    let mut_ref: &amp;amp;mut WindowThreadState = &amp;amp;mut window_state;

    // next we need to convert the reference to a pointer
    let raw_ptr: *mut WindowThreadState = mut_ref as *mut WindowThreadState;

    // and the pointer type we can cast to the c_void type required by CreateWindowEx
    let void_ptr: *mut winapi::ctypes::c_void = raw_ptr as *mut winapi::ctypes::c_void;

    // all steps expressed in a single line
    &amp;amp;mut window_state as *mut WindowThreadState as *mut winapi::ctypes::c_void
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the state passed into CreateWindowEx, it&amp;rsquo;s time to update the message handler and remove the use of the global state.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
unsafe extern &amp;quot;system&amp;quot; fn window_proc(
    h_wnd: HWND,    
    msg: UINT,
    w_param: WPARAM,
    l_param: LPARAM,
) -&amp;gt; LRESULT {

    if msg == WM_CREATE {
        // retrieve the message struct that contains the creation parameters
        let create_struct = l_param as * mut winapi::um::winuser::CREATESTRUCTW;
    
        // retrieve the rust window state
        let window_state_ptr = create_struct.as_ref().unwrap().lpCreateParams as * mut WindowThreadState;
        let window_state : &amp;amp; mut WindowThreadState = window_state_ptr.as_mut().unwrap();

        // the pointer we can store inside of the USERDATA of the window being created
        SetWindowLongPtrW(h_wnd, GWLP_USERDATA, window_state_ptr as isize );

        // sent a message that the window has been created
        window_state.message_sender.send(WindowMessages::WindowCreated).unwrap();
    }

    if msg == WM_DESTROY {
        // request the state from the window USERDATA
        let window_state_ptr = GetWindowLongPtrW(h_wnd, GWLP_USERDATA) as * mut WindowThreadState;
        let window_state : &amp;amp; mut WindowThreadState = window_state_ptr.as_mut().unwrap();

        // send a message that the window has been closed
        window_state.message_sender.send(WindowMessages::WindowClosed).unwrap();
        window_state.is_window_closed = true;

        PostQuitMessage(0);
    }

    DefWindowProcW(h_wnd, msg, w_param, l_param)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After adjusting the message-loop, a Clippy warning needs to be disabled too.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    #[allow(clippy::while_immutable_condition)] 
    while !window_state.is_window_closed {
        if PeekMessageA(&amp;amp;mut msg, h_wnd_window, 0, 0, PM_REMOVE) &amp;gt; 0 {
            TranslateMessage(&amp;amp;msg);
            DispatchMessageA(&amp;amp;msg);
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This needs to be done because the Rust compiler can&amp;rsquo;t see that &lt;code&gt;is_window_closed&lt;/code&gt; will ever be changed. This variable is only changed in the window message proc, and Rust is unaware that this function is ever called during TranslateMessage by the windows runtime.&lt;/p&gt;

&lt;p&gt;Therefore we need to disable the Clippy warning for this location only.&lt;/p&gt;

&lt;h2 id=&#34;update&#34;&gt;Update&lt;/h2&gt;

&lt;p&gt;Turns out, there is a better way to exit the message loop.
Thanks to &lt;a href=&#34;https://twitter.com/MichalZiulek/&#34; target=&#34;_blank&#34;&gt;Michal Ziulek&lt;/a&gt; for pointing this out.&lt;/p&gt;

&lt;p&gt;&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;PostQuitMessage(0) pushes WM_QUIT message to the queue so you can break the main loop like this:&lt;br&gt;{&lt;br&gt; TranslateMessage(&amp;amp;msg);&lt;br&gt; DispatchMessageA(&amp;amp;msg);&lt;br&gt; if (msg.message == WM_QUIT) break;&lt;br&gt;}&lt;/p&gt;&amp;mdash; Michal Ziulek (@MichalZiulek) &lt;a href=&#34;https://twitter.com/MichalZiulek/status/1200844212415213572?ref_src=twsrc%5Etfw&#34;&gt;November 30, 2019&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;The updated code looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;loop {
    if PeekMessageA(&amp;amp;mut msg, h_wnd_window, 0, 0, PM_REMOVE) &amp;gt; 0 {
        TranslateMessage(&amp;amp;msg);
        DispatchMessageA(&amp;amp;msg);

        // once the window has been closed we can exit the message loop
        if msg.message == WM_QUIT {
            break;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a lot better, I can remove &lt;code&gt;is_window_closed&lt;/code&gt;, and no Clippy warning need to be disabled.&lt;/p&gt;

&lt;p&gt;With the foundation created I will focus on creating a D3D11 device next week.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-4&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game - Part 3 - Unlock the Message Loop</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-3/</link>
      <pubDate>Fri, 22 Nov 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-3/</guid>
      <description>

&lt;p&gt;With the implementation from the previous post, the game loop stops updating when dragging the window.&lt;/p&gt;

&lt;p&gt;This happens because the windows message loop is continuously receiving new messages.  This causes &lt;code&gt;process_window_messages&lt;/code&gt; to enter an endless loop until the user stops dragging the window.&lt;/p&gt;

&lt;p&gt;I personally like to keep my game updating at all times; therefore, I move my windows message loop processing into a background thread.&lt;/p&gt;

&lt;p&gt;The following two steps are required to make sure that game loop updates at all times:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a window in a thread and run the message pump in the window thread&lt;/li&gt;
&lt;li&gt;Setup thread-safe communication between game thread and message loop thread&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;creating-window-in-a-thread&#34;&gt;Creating window in a thread&lt;/h3&gt;

&lt;p&gt;Creating the window in a thread requires very few changes to the code shown in the previous post.&lt;/p&gt;

&lt;p&gt;Moving the code from &lt;code&gt;create_window&lt;/code&gt; into a &lt;code&gt;std::thread::spawn&lt;/code&gt; closure&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;std::thread::spawn(move || { 
    let mut window_class_name: Vec&amp;lt;u16&amp;gt; =
                OsStr::new(&amp;quot;Match3WindowClass&amp;quot;).encode_wide().collect();

            window_class_name.push(0);

            let window_class = WNDCLASSW {
                style: 0,
                lpfnWndProc: Some(window_proc),
                ........

            let h_wnd_window = CreateWindowExW(
                ........
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will make sure the window is created in a new thread.&lt;/p&gt;

&lt;p&gt;The message loop needs to run in the same thread as the window was created. Therefore the &amp;lsquo;process_window_messages&amp;rsquo; logic needs to be moved into the thread closure as well.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    ShowWindow(h_wnd_window, SW_SHOW);

    while !IS_WINDOW_CLOSED {
        if PeekMessageA(&amp;amp;mut msg, h_wnd_window, 0, 0, PM_REMOVE) &amp;gt; 0 {
            TranslateMessage(&amp;amp;msg);
            DispatchMessageA(&amp;amp;msg);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this in place, the new thread will be receiving and processing all messages that are sent to the window.&lt;/p&gt;

&lt;p&gt;When specific messages (window closed, key pressed, &amp;hellip;), are received, they need to be sent to the game so it can react to it.&lt;/p&gt;

&lt;h3 id=&#34;setup-thread-safe-communication-between-game-and-message-loop-thread&#34;&gt;Setup thread-safe communication between game and message loop thread&lt;/h3&gt;

&lt;p&gt;One common communication primitive between threads provided by Rust is &lt;code&gt;std::sync::mpsc::channel&lt;/code&gt;
This is a &amp;ldquo;multi-producer, single-consumer FIFO queue.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;My communication strategy is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The window is the producer of messages, the game is the receiver&lt;/li&gt;
&lt;li&gt;All messages will be expressed as &lt;code&gt;enum WindowMessages&lt;/code&gt; to be sent between threads&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If I remember it correctly, some transitions, such as fullscreen, also require the game thread to be able to send messages to the window thread, but I will implement that if necessary in the future.&lt;/p&gt;

&lt;p&gt;For now, I am going to define two messages.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;WindowCreated&lt;/li&gt;
&lt;li&gt;WindowClosed&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code&gt;enum WindowMessages {
    WindowCreated,
    WindowClosed,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A channel needs to be created so that communication between the two threads is possible.&lt;/p&gt;

&lt;p&gt;The channel is created on the main thread, and the &lt;code&gt;move&lt;/code&gt; at the closure level means that ownership for variables accessed from the thread will be moved onto the spawned thread.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fn create_window() -&amp;gt; Result&amp;lt;Window, ()&amp;gt; {
    let (channel_sender, channel_receiver) = std::sync::mpsc::channel();

    std::thread::spawn(move || {
                       ----

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After the window has been created and show the &amp;lsquo;WindowCreated&amp;rsquo; message will be sent from the window thread.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;ShowWindow(h_wnd_window, SW_SHOW);

channel_sender.send(WindowMessages::WindowCreated)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because &lt;code&gt;channel_sender&lt;/code&gt; is used inside of the closure, ownership will be moved to the window thread.
&lt;code&gt;channel_receiver&lt;/code&gt; is not used, and therefore ownership stays with the game thread.&lt;/p&gt;

&lt;p&gt;Before &lt;code&gt;create_window&lt;/code&gt; returns, the window creation on the separate thread has to be completed, therefor we wait until the window creation on the separate thread has been completed.&lt;/p&gt;

&lt;p&gt;This is done as below, &lt;code&gt;channel_receiver.recv()&lt;/code&gt; will block until a message has been received.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn create_window() -&amp;gt; Result&amp;lt;Window, ()&amp;gt; {
    let (channel_sender, channel_receiver) = std::sync::mpsc::channel();

    std::thread::spawn(move || { ...... } );

    // wait for window created before returning
    if let WindowMessages::WindowCreated = channel_receiver.recv().unwrap() {
        return Ok(Window {
            message_receiver: channel_receiver,
        });
    }

    Err(())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;process_window_messages&lt;/code&gt; needs to be adjusted so that it checks for the arrival of new messages from the window channel.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn process_window_messages(window: &amp;amp;Window) -&amp;gt; Option&amp;lt;WindowMessages&amp;gt; {
    if let Ok(x) = window.message_receiver.try_recv() {
        return Some(x);
    }

    None
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;try_recv&lt;/code&gt; will not block and returns an Optional&lt;T&gt; to indicate if a new message has been received or not.&lt;/p&gt;

&lt;p&gt;The one message to be handled for now is WindowClosed.
For this, to work, the message pump on the window thread needs to send a WindowClosed event when a WM_DESTROY message has been received.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;while !IS_WINDOW_CLOSED {
    if PeekMessageA(&amp;amp;mut msg, h_wnd_window, 0, 0, PM_REMOVE) &amp;gt; 0 {
        TranslateMessage(&amp;amp;msg);
        DispatchMessageA(&amp;amp;msg);

        if IS_WINDOW_CLOSED {
            channel_sender.send(WindowMessages::WindowClosed).unwrap();
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With all this in place, we can now drag the window, and the game loop continues to update.
When the user closes the window, the game loop will close as expected.&lt;/p&gt;

&lt;p&gt;One thing that is still problematic is the global state (&lt;code&gt;IS_WINDOW_CLOSED&lt;/code&gt;) that is used for communication between the window_proc and the message loop on the message loop thread.&lt;/p&gt;

&lt;p&gt;Next, I will try to solve this and see if it&amp;rsquo;s possible to attach Rust objects to native objects.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-3&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game - Part 2 - Win32 Window</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-2/</link>
      <pubDate>Thu, 14 Nov 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-2/</guid>
      <description>

&lt;p&gt;Creating a window from Rust requires interfacing with the Win32 API.&lt;/p&gt;

&lt;p&gt;I started out using the Foreign Function Interface(FFI) to call the Win32 APIs directly.
Even though I got it working it takes a tremendous amount of effort;&lt;/p&gt;

&lt;p&gt;Thankfully, there is the &lt;a href=&#34;https://crates.io/crates/winapi&#34; target=&#34;_blank&#34;&gt;winapi&lt;/a&gt; crate.
Happy to support Peter Atashian on &lt;a href=&#34;https://www.patreon.com/retep998/overview&#34; target=&#34;_blank&#34;&gt;patreon&lt;/a&gt; for maintaining this project.&lt;/p&gt;

&lt;p&gt;To start using it, add the necessary dependency into Cargo.toml.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;[dependencies]
winapi = { version = &amp;quot;0.3&amp;quot;, features = [&amp;quot;winuser&amp;quot;] }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The features list defines what win32 APIs are required and should be imported.&lt;/p&gt;

&lt;p&gt;To detect which features are required to be compiled, search the &lt;a href=&#34;https://docs.rs/winapi/latest/winapi/&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt; for the function you want to call. It will show which module it is defined in.&lt;/p&gt;

&lt;p&gt;For example, in this case, winuser needs to be imported.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;winapi::um::winuser::CreateWindowExW
            ------
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating a Win32 window is broken down into 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;register a window class&lt;/li&gt;
&lt;li&gt;create a window&lt;/li&gt;
&lt;li&gt;start processing the message loop&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&amp;rsquo;s look at each step:&lt;/p&gt;

&lt;h2 id=&#34;register-a-window-class&#34;&gt;register a window class&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;unsafe {
    let mut window_class_name: Vec&amp;lt;u16&amp;gt; =
        OsStr::new(&amp;quot;Match3WindowClass&amp;quot;).encode_wide().collect();

    // encode_wide does NOT add a null terminator
    window_class_name.push(0);

    let window_class = WNDCLASSW {
        style: 0,
        lpfnWndProc: Some(window_proc),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: 0 as HINSTANCE,
        hIcon: 0 as HICON,
        hCursor: 0 as HICON,
        hbrBackground: 16 as HBRUSH,
        lpszMenuName: 0 as LPCWSTR,
        lpszClassName: window_class_name.as_ptr(),
    };

    let error_code = RegisterClassW(&amp;amp;window_class);

    assert!(error_code != 0, &amp;quot;failed to register the window class&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;os-string-handling&#34;&gt;OS String handling&lt;/h3&gt;

&lt;p&gt;I am using the wide version of the Win32 API.
Therefore I need to convert from the Rust OsStr into a wide-character array.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;encode_wide()&lt;/code&gt; provides the conversion into UTF16 characters. The conversion is implemented lazily as an iterator and &lt;code&gt;collect()&lt;/code&gt; collects all the u16 values into a &lt;code&gt;Vec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important to remember that &lt;code&gt;encode_wide()&lt;/code&gt; does not add null termination, and explicit zero termination is required.&lt;/p&gt;

&lt;h3 id=&#34;window-proc-handler&#34;&gt;window proc handler&lt;/h3&gt;

&lt;p&gt;You might have noticed &lt;code&gt;Some(window_proc)&lt;/code&gt; in the previous class registration.
This defines the function that will be called by Win32 to process the window messages.&lt;/p&gt;

&lt;p&gt;The function needs a bit of extra information to be passed across the Rust &amp;lt;-&amp;gt; Win32 boundary.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unsafe extern &amp;quot;system&amp;quot; fn window_proc(
    h_wnd: HWND,
    msg: UINT,
    w_param: WPARAM,
    l_param: LPARAM,
) -&amp;gt; LRESULT {
    if msg == WM_DESTROY {
        IS_WINDOW_CLOSED = true;

        PostQuitMessage(0);
    }

    DefWindowProcW(h_wnd, msg, w_param, l_param)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;unsafe extern &amp;quot;system&amp;quot;&lt;/code&gt; marks the function as unsafe and to use the system &lt;a href=&#34;https://doc.rust-lang.org/reference/items/external-blocks.html#abi&#34; target=&#34;_blank&#34;&gt;ABI&lt;/a&gt;. This is the cross-platform string that maps to stdcall on Windows.&lt;/p&gt;

&lt;h2 id=&#34;create-window&#34;&gt;Create window&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;
let h_wnd_window = CreateWindowExW(
    0,
    window_class_name.as_ptr(),
    0 as LPCWSTR,
    WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
    0,
    0,
    400,
    400,
    0 as HWND,
    0 as HMENU,
    0 as HINSTANCE,
    std::ptr::null_mut(),
);

assert!(h_wnd_window != (0 as HWND), &amp;quot;failed to open the window&amp;quot;);

ShowWindow(h_wnd_window, SW_SHOW);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating the window is pretty straightforward. Passing in the required settings and the name of the class we registered previously.&lt;/p&gt;

&lt;h2 id=&#34;message-loop&#34;&gt;Message loop&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;
let mut msg: MSG = std::mem::zeroed();

// process messages
while !IS_WINDOW_CLOSED {
    if PeekMessageA(&amp;amp;mut msg, h_wnd_window, 0, 0, PM_REMOVE) &amp;gt; 0 {
        TranslateMessage(&amp;amp;msg);
        DispatchMessageA(&amp;amp;msg);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Running the message loop is very close to the native Win32 version.
&lt;code&gt;std::mem::zeroed&lt;/code&gt; makes sure that MSG is set to an all-zero byte-pattern.&lt;/p&gt;

&lt;p&gt;Every message will now call the &lt;code&gt;window_proc&lt;/code&gt; function that was registered with the window class.&lt;/p&gt;

&lt;p&gt;Running the application will now show a default Win32 window.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/empty_win32_window.png&#34; alt=&#34;Empty Win32 Window&#34; title=&#34;Empty Win32 Window&#34; /&gt;&lt;/p&gt;

&lt;p&gt;When running the application and starting to drag the window, the main game loop stops updating.
Next week I am going to change that and look at threading in Rust.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/jendrikillner/RustMatch3/releases/tag/rust-game-part-2&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rust Game - Part 1 - Overview</title>
      <link>https://www.jendrikillner.com/post/rust-game-part-1/</link>
      <pubDate>Thu, 07 Nov 2019 04:00:00 +0000</pubDate>
      
      <guid>https://www.jendrikillner.com/post/rust-game-part-1/</guid>
      <description>&lt;p&gt;This is the start of a series of small posts about my game development endeavors using Rust.
I have been using Rust more and more in my free time projects but never used it in a larger project.&lt;/p&gt;

&lt;p&gt;This will be my first larger project using Rust, and I will talk about my learnings here.
So what I am making?&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.jendrikillner.com/img/posts/rust-game-series-match3/game_design.png&#34; alt=&#34;alt text&#34; title=&#34;Expected Visual Result&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Going to make a simple &amp;ldquo;Match 3&amp;rdquo; game from scratch.&lt;/p&gt;

&lt;p&gt;My goals for the final project result are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement full game-flow (Menus, Options, Loading, Gameplay, Pause screen, etc.)&lt;/li&gt;
&lt;li&gt;Multiple levels&lt;/li&gt;
&lt;li&gt;Save game system&lt;/li&gt;
&lt;li&gt;Audio (Music and Sound Effects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Constraints&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows only&lt;/li&gt;
&lt;li&gt;fixed resolution&lt;/li&gt;
&lt;li&gt;D3D11 renderer&lt;/li&gt;
&lt;li&gt;using no external crates at runtime, besides &lt;a href=&#34;https://crates.io/crates/winapi&#34; target=&#34;_blank&#34;&gt;winapi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools might be using some crates, but I want to keep the game itself free from external dependencies as much as possible.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>