diff --git a/.azuredevops/pipelines/DirectXTK-GitHub-CMake-Dev17.yml b/.azuredevops/pipelines/DirectXTK-GitHub-CMake-Dev17.yml index 51573d3b9..1e62bd271 100644 --- a/.azuredevops/pipelines/DirectXTK-GitHub-CMake-Dev17.yml +++ b/.azuredevops/pipelines/DirectXTK-GitHub-CMake-Dev17.yml @@ -57,7 +57,7 @@ variables: Codeql.Enabled: false VS_GENERATOR: 'Visual Studio 17 2022' WIN10_SDK: '10.0.19041.0' - WIN11_SDK: '10.0.22000.0' + WIN11_SDK: '10.0.26100.0' pool: vmImage: windows-2022 diff --git a/.azuredevops/pipelines/DirectXTK-GitHub-CMake.yml b/.azuredevops/pipelines/DirectXTK-GitHub-CMake.yml index 469675c1c..4cc379d88 100644 --- a/.azuredevops/pipelines/DirectXTK-GitHub-CMake.yml +++ b/.azuredevops/pipelines/DirectXTK-GitHub-CMake.yml @@ -57,7 +57,7 @@ variables: Codeql.Enabled: false VS_GENERATOR: 'Visual Studio 17 2022' WIN10_SDK: '10.0.19041.0' - WIN11_SDK: '10.0.22000.0' + WIN11_SDK: '10.0.26100.0' pool: vmImage: windows-2022 diff --git a/.azuredevops/pipelines/DirectXTK-GitHub-MinGW.yml b/.azuredevops/pipelines/DirectXTK-GitHub-MinGW.yml index e01fb3f8f..754813cfe 100644 --- a/.azuredevops/pipelines/DirectXTK-GitHub-MinGW.yml +++ b/.azuredevops/pipelines/DirectXTK-GitHub-MinGW.yml @@ -77,7 +77,7 @@ variables: - name: VCPKG_MANIFEST_DIR value: '$(Build.SourcesDirectory)/build' - name: WIN11_SDK - value: '10.0.22000.0' + value: '10.0.26100.0' - name: BASE_URL value: https://github.com/brechtsanders/winlibs_mingw/releases/download - name: URL_MINGW32 @@ -90,6 +90,7 @@ variables: jobs: - job: MINGW32_BUILD displayName: 'Minimalist GNU for Windows (MinGW32)' + timeoutInMinutes: 30 steps: - checkout: self clean: true @@ -178,6 +179,7 @@ jobs: - job: MINGW64_BUILD displayName: 'Minimalist GNU for Windows (MinGW-W64) BUILD_TESTING=ON' + timeoutInMinutes: 90 steps: - checkout: self clean: true diff --git a/.azuredevops/pipelines/DirectXTK-OneFuzz-Audio.yml b/.azuredevops/pipelines/DirectXTK-OneFuzz-Audio.yml index eeba932e2..091a36919 100644 --- a/.azuredevops/pipelines/DirectXTK-OneFuzz-Audio.yml +++ b/.azuredevops/pipelines/DirectXTK-OneFuzz-Audio.yml @@ -32,7 +32,7 @@ name: $(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r) variables: Codeql.Enabled: false VS_GENERATOR: 'Visual Studio 17 2022' - WIN11_SDK: '10.0.22000.0' + WIN11_SDK: '10.0.26100.0' pool: vmImage: windows-2022 diff --git a/.azuredevops/pipelines/DirectXTK-OneFuzz-Meshes.yml b/.azuredevops/pipelines/DirectXTK-OneFuzz-Meshes.yml index 8484f19e2..03c840151 100644 --- a/.azuredevops/pipelines/DirectXTK-OneFuzz-Meshes.yml +++ b/.azuredevops/pipelines/DirectXTK-OneFuzz-Meshes.yml @@ -32,7 +32,7 @@ name: $(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r) variables: Codeql.Enabled: false VS_GENERATOR: 'Visual Studio 17 2022' - WIN11_SDK: '10.0.22000.0' + WIN11_SDK: '10.0.26100.0' pool: vmImage: windows-2022 diff --git a/.azuredevops/pipelines/DirectXTK-OneFuzz.yml b/.azuredevops/pipelines/DirectXTK-OneFuzz.yml index 3633f9c15..1134e5a7f 100644 --- a/.azuredevops/pipelines/DirectXTK-OneFuzz.yml +++ b/.azuredevops/pipelines/DirectXTK-OneFuzz.yml @@ -32,7 +32,7 @@ name: $(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r) variables: Codeql.Enabled: false VS_GENERATOR: 'Visual Studio 17 2022' - WIN11_SDK: '10.0.22000.0' + WIN11_SDK: '10.0.26100.0' pool: vmImage: windows-2022 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index fba578941..746d029c1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -23,7 +23,7 @@ These instructions define how GitHub Copilot should assist with this project. Th - **Documentation**: The project provides documentation in the form of wiki pages available at [Documentation](https://github.com/microsoft/DirectXTK/wiki/). - **Error Handling**: Use C++ exceptions for error handling and uses RAII smart pointers to ensure resources are properly managed. For some functions that return HRESULT error codes, they are marked `noexcept`, use `std::nothrow` for memory allocation, and should not throw exceptions. - **Testing**: Unit tests for this project are implemented in this repository [Test Suite](https://github.com/walbourn/directxtktest/) and can be run using CTest per the instructions at [Test Documentation](https://github.com/walbourn/directxtktest/wiki). -- **Security**: This project uses secure coding practices from the Microsoft Secure Coding Guidelines, and is subject to the `SECURITY.md` file in the root of the repository. Functions that read input from image file, geometry files, and audio files are subject to OneFuzz testing to ensure they are secure against malformed files. +- **Security**: This project uses secure coding practices from the Microsoft Secure Coding Guidelines, and is subject to the `SECURITY.md` file in the root of the repository. Functions that read input from image file, geometry files, and audio files are subject to OneFuzz fuzz testing to ensure they are secure against malformed files. - **Dependencies**: The project uses CMake and VCPKG for managing dependencies, making optional use of DirectXMath, GameInput, and XAudio2Redist. The project can be built without these dependencies, relying on the Windows SDK for core functionality. - **Continuous Integration**: This project implements GitHub Actions for continuous integration, ensuring that all code changes are tested and validated before merging. This includes building the project for a number of configurations and toolsets, running a subset of unit tests, and static code analysis including GitHub super-linter, CodeQL, and MSVC Code Analysis. - **Code of Conduct**: The project adheres to the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). All contributors are expected to follow this code of conduct in all interactions related to the project. @@ -65,12 +65,13 @@ Tests/ # Tests are designed to be cloned from a separate repository at ## References +- [Source git repository on GitHub](https://github.com/microsoft/DirectXTK.git) +- [DirectXTK documentation git repository on GitHub](https://github.com/microsoft/DirectXTK.wiki.git) +- [DirectXTK test suite git repository on GitHub](https://github.com/walbourn/directxtktest.wiki.git). - [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) - [Microsoft Secure Coding Guidelines](https://learn.microsoft.com/en-us/security/develop/secure-coding-guidelines) - [CMake Documentation](https://cmake.org/documentation/) -- [VCPK Documentation](https://learn.microsoft.com/vcpkg/) -- [DirectX Tool Kit for DirectX 11 Wiki](https://github.com/microsoft/DirectXTK/wiki/) -- [DirectX Tool Kit for Audio Wiki](https://github.com/Microsoft/DirectXTK/wiki/Audio) +- [VCPKG Documentation](https://learn.microsoft.com/vcpkg/) - [Games for Windows and the DirectX SDK blog - March 2012](https://walbourn.github.io/directxtk/) - [Games for Windows and the DirectX SDK blog - January 2013](https://walbourn.github.io/directxtk-update/) - [Games for Windows and the DirectX SDK blog - December 13](https://walbourn.github.io/directx-tool-kit-for-audio/) @@ -107,3 +108,28 @@ When creating documentation: - Review each documented item against source code whenever related to the task. - Remove any speculative content. - Ensure all documentation is verifiable against the current state of the codebase. + +## Code Review Instructions + +When reviewing code, focus on the following aspects: + +- Adherence to coding standards defined in `.editorconfig` and on the [wiki](https://github.com/microsoft/DirectXTK/wiki/Implementation). +- Make coding recommendations based on the *C++ Core Guidelines*. +- Proper use of RAII and smart pointers. +- Correct error handling practices and C++ Exception safety. +- Clarity and maintainability of the code. +- Adequate comments where necessary. +- Public interfaces are located in `Inc\*.h` should be clearly defined and documented on the GitHub wiki. +- Compliance with the project's architecture and design patterns. +- Ensure that all public functions and classes are covered by unit tests located on [GitHub](https://github.com/walbourn/directxtktest.git) where applicable. Report any gaps in test coverage. +- Check for performance implications, especially in geometry processing algorithms. +- Provide brutally honest feedback on code quality, design, and potential improvements as needed. + +## Documentation Review Instructions + +When reviewing documentation, do the following: + +- Read the code located in [this git repository](https://github.com/microsoft/DirectXTK.git) in the main branch. +- Review the public interface defined in the `Inc` folder. +- Read the documentation on the wiki located in [this git repository](https://github.com/microsoft/DirectXTK.wiki.git). +- Report any specific gaps in the documentation compared to the public interface. diff --git a/.gitignore b/.gitignore index f9995f0e2..18195527a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ *.VC.db *.nupkg .vs +.vscode Bin packages /Src/Shaders/Compiled/*.inc diff --git a/Audio/SoundCommon.cpp b/Audio/SoundCommon.cpp index b9f085efa..cd5a62581 100644 --- a/Audio/SoundCommon.cpp +++ b/Audio/SoundCommon.cpp @@ -895,7 +895,7 @@ void AudioListener::SetCone(const X3DAUDIO_CONE& listenerCone) pCone = &ListenerCone; } -bool AudioListener::IsValid() const +bool AudioListener::IsValid() const noexcept { if (!std::isfinite(OrientFront.x)) return false; @@ -943,7 +943,7 @@ void AudioEmitter::SetCone(const X3DAUDIO_CONE& emitterCone) pCone = &EmitterCone; } -bool AudioEmitter::IsValid() const +bool AudioEmitter::IsValid() const noexcept { if (!std::isfinite(OrientFront.x)) return false; diff --git a/CMakeLists.txt b/CMakeLists.txt index bffafc65a..5edb4ed87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,8 @@ option(ENABLE_CODE_ANALYSIS "Use Static Code Analysis on build" OFF) option(ENABLE_CODE_COVERAGE "Build with code-coverage" OFF) +option(ENABLE_CODE_PROFILING "Build for profiling" OFF) + option(USE_PREBUILT_SHADERS "Use externally built HLSL shaders" OFF) option(NO_WCHAR_T "Use legacy wide-character as unsigned short" OFF) @@ -482,6 +484,13 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endforeach() endif() + if(ENABLE_CODE_PROFILING) + message(STATUS "Building with /PROFILE") + foreach(t IN LISTS TOOL_EXES ITEMS ${PROJECT_NAME}) + target_link_options(${t} PRIVATE /profile) + endforeach() + endif() + if(ENABLE_SPECTRE_MITIGATION AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.13) AND (NOT WINDOWS_STORE)) diff --git a/Inc/Audio.h b/Inc/Audio.h index a6e16958a..ffb3896fb 100644 --- a/Inc/Audio.h +++ b/Inc/Audio.h @@ -611,7 +611,7 @@ namespace DirectX void __cdecl SetCone(const X3DAUDIO_CONE& listenerCone); - bool __cdecl IsValid() const; + bool __cdecl IsValid() const noexcept; }; @@ -732,7 +732,7 @@ namespace DirectX pReverbCurve = nullptr; } - bool __cdecl IsValid() const; + bool __cdecl IsValid() const noexcept; }; diff --git a/Inc/Keyboard.h b/Inc/Keyboard.h index 87b24dcb3..3e5c75f59 100644 --- a/Inc/Keyboard.h +++ b/Inc/Keyboard.h @@ -531,7 +531,7 @@ namespace DirectX } #endif #elif defined(WM_USER) - DIRECTX_TOOLKIT_API static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); + DIRECTX_TOOLKIT_API static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) noexcept; #endif // Singleton diff --git a/Src/BufferHelpers.cpp b/Src/BufferHelpers.cpp index 6bdd1f74d..85a0a8f9f 100644 --- a/Src/BufferHelpers.cpp +++ b/Src/BufferHelpers.cpp @@ -360,6 +360,9 @@ void Private::ConstantBufferBase::CreateBuffer( size_t bytes, ID3D11Buffer** pBuffer) { + if (!device) + throw std::invalid_argument("Direct3D device is null"); + if (!pBuffer) throw std::invalid_argument("ConstantBuffer needs valid buffer parameter"); diff --git a/Src/CommonStates.cpp b/Src/CommonStates.cpp index 982997aea..97aff13cc 100644 --- a/Src/CommonStates.cpp +++ b/Src/CommonStates.cpp @@ -187,8 +187,12 @@ HRESULT CommonStates::Impl::CreateSamplerState( // Public constructor. CommonStates::CommonStates(_In_ ID3D11Device* device) - : pImpl(Impl::instancePool.DemandCreate(device)) -{} +{ + if (!device) + throw std::invalid_argument("Direct3D device is null"); + + pImpl = Impl::instancePool.DemandCreate(device); +} CommonStates::CommonStates(CommonStates&&) noexcept = default; diff --git a/Src/EffectFactory.cpp b/Src/EffectFactory.cpp index 1ce16b034..7ca817555 100644 --- a/Src/EffectFactory.cpp +++ b/Src/EffectFactory.cpp @@ -68,6 +68,9 @@ class EffectFactory::Impl mUseNormalMapEffect(true), mForceSRGB(false) { + if (!device) + throw std::invalid_argument("Direct3D device is null"); + if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) { mUseNormalMapEffect = false; diff --git a/Src/GeometricPrimitive.cpp b/Src/GeometricPrimitive.cpp index 22804f582..e7161e8b6 100644 --- a/Src/GeometricPrimitive.cpp +++ b/Src/GeometricPrimitive.cpp @@ -160,6 +160,9 @@ void GeometricPrimitive::Impl::SharedResources::PrepareForRendering(bool alpha, _Use_decl_annotations_ void GeometricPrimitive::Impl::Initialize(ID3D11DeviceContext* deviceContext, const VertexCollection& vertices, const IndexCollection& indices) { + if (!deviceContext) + throw std::invalid_argument("Direct3D device context is null"); + if (vertices.size() >= USHRT_MAX) throw std::out_of_range("Too many vertices for 16-bit index buffer"); diff --git a/Src/Keyboard.cpp b/Src/Keyboard.cpp index 5982d0e95..7a96d8b19 100644 --- a/Src/Keyboard.cpp +++ b/Src/Keyboard.cpp @@ -214,7 +214,7 @@ class Keyboard::Impl Keyboard::Impl* Keyboard::Impl::s_keyboard = nullptr; -void Keyboard::ProcessMessage(UINT, WPARAM, LPARAM) +void Keyboard::ProcessMessage(UINT, WPARAM, LPARAM) noexcept { // GameInput for Keyboard doesn't require Win32 messages, but this simplifies integration. } @@ -535,7 +535,7 @@ class Keyboard::Impl Keyboard::Impl* Keyboard::Impl::s_keyboard = nullptr; -void Keyboard::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) +void Keyboard::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) noexcept { auto pImpl = Impl::s_keyboard; diff --git a/Src/PrimitiveBatch.cpp b/Src/PrimitiveBatch.cpp index 34db5451e..66b7fc5d1 100644 --- a/Src/PrimitiveBatch.cpp +++ b/Src/PrimitiveBatch.cpp @@ -128,12 +128,13 @@ PrimitiveBatchBase::Impl::Impl(_In_ ID3D11DeviceContext* deviceContext, size_t m grfxMemoryIB(nullptr), grfxMemoryVB(nullptr) #else - mMappedIndices -{ -}, -mMappedVertices{} + mMappedIndices{}, + mMappedVertices{} #endif { + if (!deviceContext) + throw std::invalid_argument("Direct3D device context is null"); + ComPtr device; deviceContext->GetDevice(&device); diff --git a/Src/SpriteBatch.cpp b/Src/SpriteBatch.cpp index 8079ba40c..623728312 100644 --- a/Src/SpriteBatch.cpp +++ b/Src/SpriteBatch.cpp @@ -382,10 +382,14 @@ SpriteBatch::Impl::Impl(_In_ ID3D11DeviceContext* deviceContext) mSpriteQueueArraySize(0), mInBeginEndPair(false), mSortMode(SpriteSortMode_Deferred), - mTransformMatrix(MatrixIdentity), - mDeviceResources(deviceResourcesPool.DemandCreate(GetDevice(deviceContext).Get())), - mContextResources(contextResourcesPool.DemandCreate(deviceContext)) -{} + mTransformMatrix(MatrixIdentity) +{ + if (!deviceContext) + throw std::invalid_argument("Direct3D device context is null"); + + mDeviceResources = deviceResourcesPool.DemandCreate(GetDevice(deviceContext).Get()); + mContextResources = contextResourcesPool.DemandCreate(deviceContext); +} // Begins a batch of sprite drawing operations. diff --git a/Src/SpriteFont.cpp b/Src/SpriteFont.cpp index 6f806af6f..e6025d3d5 100644 --- a/Src/SpriteFont.cpp +++ b/Src/SpriteFont.cpp @@ -46,12 +46,6 @@ class SpriteFont::Impl template void ForEachGlyph(_In_z_ wchar_t const* text, TAction action, bool ignoreWhitespace) const; - void CreateTextureResource(_In_ ID3D11Device* device, - uint32_t width, uint32_t height, - DXGI_FORMAT format, - uint32_t stride, uint32_t rows, - _In_reads_(stride * rows) const uint8_t* data) noexcept(false); - const wchar_t* ConvertUTF8(_In_z_ const char *text) noexcept(false); // Fields. @@ -62,6 +56,12 @@ class SpriteFont::Impl float lineSpacing; private: + void CreateTextureResource(_In_ ID3D11Device* device, + uint32_t width, uint32_t height, + DXGI_FORMAT format, + uint32_t stride, uint32_t rows, + _In_reads_(stride * rows) const uint8_t* data) noexcept(false); + size_t utfBufferSize; std::unique_ptr utfBuffer; }; @@ -103,6 +103,9 @@ SpriteFont::Impl::Impl( lineSpacing(0), utfBufferSize(0) { + if (!device || !reader) + throw std::invalid_argument("Direct3D device is null"); + // Validate the header. for (char const* magic = spriteFontMagic; *magic; magic++) {