A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/microsoft/DirectXTK/wiki/Implementation below:

Implementation · microsoft/DirectXTK Wiki · GitHub

The project includes an .editorconfig file which enforces basic editor and formatting conventions. There is a GitHub Action running GitHub's super-linter to run editorconfig-checker, yamllint, markdownlint, and other tools.

For Visual C++, the projects make use of the default C++11/C++14 mode rather than /std:c++17 mode, although occasionally run a validation pass to confirm it's fully compatible with C++17 (i.e. avoid all use of auto_ptr, random_shuffle, and other deprecated features). The library does not make use of newer C++17 language & library features such as string_view, static_assert without a message, etc. although that may change in the future. The projects make use of /Wall, /permissive-, /Zc:__cplusplus, and /analyze to ensure a high-level of C++ conformance.

For the few cases (such as if constexpr or [[fallthrough]]) where it's important to have a C++17 feature used for better code-generation, use a #if (__cplusplus >= 201703L) guard for now.

For clang/LLVM for Windows, there is a CMakeList.txt provided to validate the code and ensure a high-level of conformance. This primarily means addressing warnings generated using /Wall -Wpedantic -Wextra.

A few of the implementation modules and headers support Windows Subsystem for Linux via GNUC, so in those cases we leverage C++17 mode to get it to build. For example, the std::size helper is in Visual C++ 2015 Update 3 or later even in the default C++11/C++14 mode, but for GNUC it's only there with C++17 mode enabled.

Another example is std::aligned_alloc which is a C++17 portable function for allocated aligned memory, but it's not supported with Windows. Instead you have to continue to use _aligned_malloc / _aligned_free. For aligned structures, we use DirectXMath's XM_ALIGNED_STRUCT(x) macro. In DirectXMath 3.15 or later, this supports Visual C++, clang/LLVM for Windows, and GNUC compilers.

While the DirectX Tool Kit design is heavily influenced by the XNA Game Studio framework C# object design, it uses C++ conventions consistent with modern Win32 APIs rather than the strict .NET use of PascalCase as enforced by FXCop.

The library does not generally make use of Hungarian notation which as been deprecated for Win32 C++ APIs for many years, with the exception of a few uses of p for pointers and sz for strings.

The use of Standard C++ types is preferred including the fundamental types supplied by the language (i.e. int, unsigned int, size_t, ptrdiff_t, bool, true/false, char, wchar_t) with the addition of the C99 fixed width types (i.e. uint32_t, uint64_t, intptr_t, uintptr_t, etc.)

Avoid using Windows "portability" types except when dealing directly with Win32 APIs: VOID, UINT, INT, DWORD, FLOAT, BOOL, TRUE/FALSE, WCHAR, CONST, etc.

Strongly-typed enum bitmask flags

To provide type-safe bitmask flags, we make use of the DEFINE_ENUM_FLAG_OPERATORS macro (in winnt.h) to make an enum work as you'd expect for bitmask flags based on recommendations in the C+ standard under 17.5.2.1.3 Bitmask types.

The impact to client code is minimal, but mostly means you can't pass a 0 literal and must use the defined default value like WIC_LOADER_DEFAULT.

We generally use enum rather than enum class because it simplifies testing the bitflags. For example, the following works with enum:

if ((myFlags & MYFLAGS_BIT2) != 0)

To do the same thing with a enum class requires:

if ((myFlags & MYFLAGS_BIT2) == MYFLAGS_BIT2)

Direct3D 11 headers do not make use of the strongly type enum bitmask flags. For this reason, if you need a parameter such as D3D11_BIND_FLAG the proper type is unsigned int.

Direct3D 12 headers have adopted strongly typed enum bitmask flags. If you need a parameter such as D3D12_RESOURCE_FLAGS the proper type is D3D12_RESOURCE_FLAGS.

See this blog post.

The Modern C++ recommendation is to use UTF-8 Everywhere except where specifically interacting with Win32 or Windows Runtime APIs which require converting to wchar_t (UTF-16LE).

Most functions in DirectX Tool Kit take wchar_t* since they are passed directly along to Win32 types. SpriteFont provides both UTF-8 char* and UTF-16LE wchar_t* methods.

DirectX Tool Kit uses a mix of Win32-style HRESULT error codes and C++ exception handling. Since the library is modeled after XNA API designs, it uses C++ exception handling for errors in most places for failures that really should never happen at runtime in a debugged program. DirectX Tool Kit also leverages a number of Standard C++ Library (STL) classes that all use C++ exceptions for error handling.

HRESULT return codes are used by DDSTextureLoader, ScreenGrab, and WICTextureLoader since that code is kept in sync for use 'standalone' where exception handling may not be desired. HRESULT is also used in a few of the helpers in BufferHelpers.h and DirectXHelpers.h to simplify cut & paste use in other contexts.

For the remainder of the APIs, they use C++ exception handling leveraging C++11 exception, stdexcept and system_error. In these cases, the method usually returns void.

throw std::invalid_argument("Invalid texture for Draw");
throw std::system_error(std::error_code(static_cast<int>(GetLastError()), std::system_category()), "CreateEventEx");
if ((sampleRate < XAUDIO2_MIN_SAMPLE_RATE) || (sampleRate > XAUDIO2_MAX_SAMPLE_RATE))
   throw std::out_of_range("Default sample rate is out of range");

In the past we used throw std::exception("what string"); but this pattern is not portable or conformant: the ctor for std::exception that takes a what string is Microsoft-specific extension. You can use throw std::exception();, but this is generally only used in sample code.

The DirectX Toolkit library makes extensive use of SAL2 annotations (_In_, _Outptr_opt_, etc.) which greatly improves the accuracy of the Visual C++ static code analysis (also known as PREFAST). The standard Windows headers #define them all to empty strings if not building with /analyze, so they have no effect on code-generation.

DirectXTK's implementation makes extensive use of the pImpl idiom. This keeps the public headers slim and minimizes inter-module dependencies.

// SpriteBatch.h public header
class SpriteBatch
{
public:
    SpriteBatch(...) noexcept(false);

    SpriteBatch(SpriteBatch&&) noexcept;
    SpriteBatch& operator= (SpriteBatch&&) noexcept;

    SpriteBatch(SpriteBatch const&) = delete;
    SpriteBatch& operator=(SpriteBatch const&) = delete;

    virtual ~SpriteBatch();
    ...

private:
    // Private implementation.
    class Impl;

    std::unique_ptr<Impl> pImpl;
};

This also allows the implementation to allocate the pImpl class internally using _aligned_malloc(x,16); so that we can use the DirectXMath aligned XMVECTOR and XMMATRIX types directly in the implementation across all architectures.

SpriteBatch::SpriteBatch(SpriteBatch&&) noexcept = default;
SpriteBatch::SpriteBatch& operator= (SpriteBatch&&) noexcept = default;
SpriteBatch::~SpriteBatch() = default;

Public methods in the library are explicitly marked __cdecl to ensure consistent behavior no matter what the client code is using. Internally it is not specified as it's assumed from the default setting except where XM_VECTORCALL is utilized (see the DirectXMath section below). Public inline functions do not need to be explicitly marked __cdecl.

This generally only matters for 32-bit (x86) platforms which have a potential mix of many calling conventions (__stdcall, __cdecl, __fastcall, or __vectorcall). For X64, ARM, and ARM64 they all generally just use one calling convention (__fastcall). For 64-bit (x64 native), the __cdecl is interpreted by the compiler as an alias for __fastcall so it's the same as annotating them with the default calling convention. It's still important to annotate exported public functions for x64 because it's possible to build the client using /Gv which assumes __vectorcall if nothing is specified.

Note that annotation for the calling-convention only has to be on the function declaration/prototype as the definition will pick it up implicitly.

The std::function is used for callbacks as a general pattern so that client code can provide function pointers, lambdas, functors, etc. To support building with a mix of calling conventions, we need to annotate the std::function correctly.

    HRESULT __cdecl SaveWICTextureToFile( /*...*/,
        std::function<void __cdecl(IPropertyBag2*)> setCustomProps
            = nullptr );
Default constructors/assignment operators

The C++11 standard includes a more efficient = default and = delete construct for dealing with special constructors and operators.

To declare a standard copy constructor and copy assignment operators, we use:

Rectangle(const Rectangle&) = default;
Rectangle& operator= (const Rectangle&) = default;

To prevent copying we use:

// Prevent copying.
SpriteBatch(SpriteBatch const&) = delete;
SpriteBatch& operator= (SpriteBatch const&) = delete;

Per C++ Core Guidelines recommendations, if you declare a copy constructor/assignment operator, you should also defined the move equivalents:

Rectangle(Rectangle&&) = default;
Rectangle& operator= (Rectangle&&) = default;

Note that use of = default can improve codegen for derived types as well.

DirectXMath Parameter Conventions

The library uses the DirectXMath calling convention types to improve parameter passing of XMVECTOR and XMMATRIX types.

The generally recommended usage of the DirectX Tool Kit is as a static C++ library. For some scenarios, however, DLL usage can be helpful and this is supported through the CMake project via BUILD_SHARED_LIBS=ON. The define DIRECTX_TOOLKIT_API is used to export/import specific classes & methods.

For classes, the primary method is to export the whole class via class DIRECTX_TOOLKIT_API X. For classes using the pImpl idiom, however, we do not want to export the Impl class. Therefore, you have to annotate each method with DIRECTX_TOOLKIT_API instead of the whole class.

MinGW has some quirks with dllimport, specifically if you use DIRECTX_TOOLKIT_API on a method declared inline within the class body, you must add a redundant inline keyword (i.e. DIRECTX_TOOLKIT_API inline) to the method which is normally not required.

Note you do not dllexport =default or =delete methods.

Dual-use Coding Techniques for Games
C++ Core Guidelines


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4