From 30c2260b4a36593cfd2821f3082969458c792fd7 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 2 Jun 2026 19:01:56 -0700 Subject: [PATCH 01/11] Convert release instructions to CoPilot skill --- .github/copilot-instructions.md | 23 +---------- .github/skills/release/SKILL.md | 67 +++++++++++++++++++++++++++++++++ .github/workflows/codeql.yml | 4 +- .github/workflows/msvc.yml | 2 +- .gitignore | 1 + 5 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 .github/skills/release/SKILL.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b12a2ff0..98792ca0 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -330,25 +330,4 @@ When reviewing documentation, do the following: ## Release Process -1. Ensure all changes are merged into the `main` branch and that all tests pass. -2. Git pull the local repository to ensure it is up to date with the `main` branch. -3. Run the PowerShell script `build\preparerelease.ps1` which will generate a topic branch for the release, update the version number in `CMakeLists.txt`, the `README.md` file, the release notes in the nuspec files, and create a stub in the `CHANGELOG.md` file for the new release. -4. Edit the `CHANGELOG.md` file to update it with a summary of changes. -5. Submit the topic branch for review and merge into `main` once approved. Allow the GitHub Actions workflows and the Azure DevOps pipelines to complete successfully before proceeding. -6. Run the PowerShell script `build\completerelease.ps1` which will set a tag on the project repo and the test repo, and create a release on GitHub with the release notes from `CHANGELOG.md`. Ensure you have set up GPG signing for your GitHub account so that the tags will be verified. -7. Git pull the local repository to ensure it is up to date with the `main` branch. Be sure to include `--tags`. -8. Push the `main` branch to the MSCodeHub mirror repository. Be sure to include `--tags`. -9. Create a PR on MSCodeHub from the `main` branch to the `release` branch. -10. Merge the PR on MSCodeHub to update the release branch, which will trigger the Azure DevOps pipeline to build the NuGet packages. -11. Edit the GitHub release and upload the signed binaries from the matching DirectXTK release to the release assets. -12. Download the GitHub source .zip archive from the release. Unzip and compare to the local repo to ensure it matches — keep in mind there may be some CR/LF differences. Run minisign on the .zip to generate a signature file, and upload the signature file to the release assets. -13. Validate the NuGet packages with by pushing the NuGet packages to a local Packages Source folder, and refreshing the NuGet packages from that folder. Then build using BuildAllSolutions.targets. -14. Run the PowerShell script `build\promotenuget.ps1` with the `-Release` parameter to promote the version to the Release view on the project-scoped ADO feed. -15. Run the MSCodeHub pipeline to publish the NuGet packages to nuget.org. The pipeline will automatically push the most recent package promoted to the Release view to nuget.org. -16. Git pull a local repository of VCPKG to `d:\vcpkg` in sync with the `main` branch of the VCPKG repository. -17. Run the PowerShell script `build\updatevcpkg.ps1` to update the DirectXTK12 port in VCPKG with the new release version. This will edit the files in `ports\directxtk12`. -18. Test the VCPKG port using all appropriate triplets and features. -19. Run `.\vcpkg --x-add-version directxtk12` to update the VCPKG versioning history. -20. Submit a PR to the VCPKG repository to update the DirectXTK12 port back to the main GitHub repo. The PR will be reviewed and merged by the VCPKG maintainers. - -> When fully completed, be sure to update the GitHub release with links to the matching NuGet packages, the VCPKG port, and the winget manifests for the tools. +The release process is documented in the [release skill](.github/skills/release/SKILL.md). Invoke the `release` skill for step-by-step guidance when performing a release. diff --git a/.github/skills/release/SKILL.md b/.github/skills/release/SKILL.md new file mode 100644 index 00000000..142bcb68 --- /dev/null +++ b/.github/skills/release/SKILL.md @@ -0,0 +1,67 @@ +--- +name: release +description: Guide for performing the DirectX Tool Kit for DirectX 12 release process. Use this skill when asked to help with releasing a new version, publishing packages, or updating ports. +--- + +# Release Process + +## Prerequisites + +- All changes merged into the `main` branch with all tests passing. +- GPG signing configured for your GitHub account (for verified tags). +- Access to the MSCodeHub mirror repository and Azure DevOps pipelines. +- Local repository: + - VCPKG at `d:\vcpkg` (synced with `main` branch) + +## Steps + +### Phase 1: Prepare the Release + +1. Git pull the local repository to ensure it is up to date with the `main` branch. +2. Run the PowerShell script `build\preparerelease.ps1` which will generate a topic branch for the release, update the version number in `CMakeLists.txt`, the `README.md` file, the release notes in the nuspec files, and create a stub in the `CHANGELOG.md` file for the new release. +3. Edit the `CHANGELOG.md` file to update it with a summary of changes. +4. Submit the topic branch for review and merge into `main` once approved. Allow the GitHub Actions workflows and the Azure DevOps pipelines to complete successfully before proceeding. + +### Phase 2: Tag and Create GitHub Release + +5. Run the PowerShell script `build\completerelease.ps1` which will set a tag on the project repo and the test repo, and create a release on GitHub with the release notes from `CHANGELOG.md`. Ensure you have set up GPG signing for your GitHub account so that the tags will be verified. +6. Git pull the local repository to ensure it is up to date with the `main` branch. Be sure to include `--tags`. + +### Phase 3: MSCodeHub and Signed Binaries + +7. Push the `main` branch to the MSCodeHub mirror repository. Be sure to include `--tags`. +8. Create a PR on MSCodeHub from the `main` branch to the `release` branch. +9. Merge the PR on MSCodeHub to update the release branch, which will trigger the Azure DevOps pipeline to build the NuGet packages. +10. Edit the GitHub release and upload the signed binaries from the matching DirectXTK release to the release assets (`xwbtool.exe`, `xwbtool_arm64.exe`, and `MakeSpriteFont.exe`). + +### Phase 4: Source Archive Signing + +11. Download the GitHub source .zip archive from the release. Unzip and compare to the local repo to ensure it matches — keep in mind there may be some CR/LF differences. +12. Run minisign on the .zip to generate a signature file, and upload the signature file to the release assets. + +### Phase 5: NuGet Validation and Publishing + +13. Validate the NuGet packages with by pushing the NuGet packages to a local Packages Source folder, and refreshing the NuGet packages from that folder. Then build using BuildAllSolutions.targets. +14. Run the PowerShell script `build\promotenuget.ps1` with the `-Release` parameter to promote the version to the Release view on the project-scoped ADO feed. +15. Run the MSCodeHub pipeline to publish the NuGet packages to nuget.org. The pipeline will automatically push the most recent package promoted to the Release view to nuget.org. + +### Phase 6: VCPKG Port Update + +16. Git pull a local repository of VCPKG to `d:\vcpkg` in sync with the `main` branch of the VCPKG repository. +17. Run the PowerShell script `build\updatevcpkg.ps1` to update the DirectXTK12 port in VCPKG with the new release version. This will edit the files in `ports\directxtk12`. +18. Test the VCPKG port using all appropriate triplets and features. +19. Run `.\vcpkg --x-add-version directxtk12` to update the VCPKG versioning history. +20. Submit a PR to the VCPKG repository to update the DirectXTK12 port back to the main GitHub repo. The PR will be reviewed and merged by the VCPKG maintainers. + +### Phase 7: Finalize + +When fully completed, be sure to update the GitHub release with links to the matching NuGet packages, the VCPKG port, and the winget manifests for the tools. + +## Key Scripts + +| Script | Purpose | +| --- | --- | +| `build\preparerelease.ps1` | Creates topic branch, updates version numbers and changelog stub | +| `build\completerelease.ps1` | Sets tags, creates GitHub release from changelog | +| `build\promotenuget.ps1 -Release` | Promotes NuGet package to Release view on ADO feed | +| `build\updatevcpkg.ps1` | Updates DirectXTK12 VCPKG port files | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f0645235..796ab144 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -61,7 +61,7 @@ jobs: - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Initialize CodeQL - uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: c-cpp build-mode: manual @@ -75,6 +75,6 @@ jobs: run: cmake --build out\build\x64-Debug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: category: "/language:c-cpp" diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 04aec958..1ea6e21b 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -78,6 +78,6 @@ jobs: # Upload SARIF file to GitHub Code Scanning Alerts - name: Upload SARIF to GitHub - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5 + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: ${{ steps.run-analysis.outputs.sarif }} diff --git a/.gitignore b/.gitignore index 7b890949..f0aad1b3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ Bin /CMakeUserPresets.json /build/vcpkg_installed /build/obj +!**/skills/** From 8a5e1b4be8c816ab2500d56169a22c2ec74f1a2b Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 2 Jun 2026 19:12:33 -0700 Subject: [PATCH 02/11] Pick markdown lint --- .github/skills/release/SKILL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/skills/release/SKILL.md b/.github/skills/release/SKILL.md index 142bcb68..7d7594d2 100644 --- a/.github/skills/release/SKILL.md +++ b/.github/skills/release/SKILL.md @@ -13,6 +13,7 @@ description: Guide for performing the DirectX Tool Kit for DirectX 12 release pr - Local repository: - VCPKG at `d:\vcpkg` (synced with `main` branch) + ## Steps ### Phase 1: Prepare the Release From fc737d59a3c53652fed0a7a69b2a4eba0ad2b20a Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 2 Jun 2026 21:53:06 -0700 Subject: [PATCH 03/11] More code review --- .github/skills/release/SKILL.md | 7 +- .github/skills/release/assets/vcpkgdxtk12.cmd | 179 ++++++++++++++++++ 2 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 .github/skills/release/assets/vcpkgdxtk12.cmd diff --git a/.github/skills/release/SKILL.md b/.github/skills/release/SKILL.md index 7d7594d2..fab7baa9 100644 --- a/.github/skills/release/SKILL.md +++ b/.github/skills/release/SKILL.md @@ -12,6 +12,7 @@ description: Guide for performing the DirectX Tool Kit for DirectX 12 release pr - Access to the MSCodeHub mirror repository and Azure DevOps pipelines. - Local repository: - VCPKG at `d:\vcpkg` (synced with `main` branch) +- PATs will be needed for scripts that access GitHub and ADO. ## Steps @@ -43,15 +44,15 @@ description: Guide for performing the DirectX Tool Kit for DirectX 12 release pr ### Phase 5: NuGet Validation and Publishing 13. Validate the NuGet packages with by pushing the NuGet packages to a local Packages Source folder, and refreshing the NuGet packages from that folder. Then build using BuildAllSolutions.targets. -14. Run the PowerShell script `build\promotenuget.ps1` with the `-Release` parameter to promote the version to the Release view on the project-scoped ADO feed. +14. Run the PowerShell script `build\promotenuget.ps1 -Version -Release` to promote the version to the Release view on the project-scoped ADO feed. The `-Version` parameter is required and should match the NuGet package version (e.g., `2026.6.2.1`). 15. Run the MSCodeHub pipeline to publish the NuGet packages to nuget.org. The pipeline will automatically push the most recent package promoted to the Release view to nuget.org. ### Phase 6: VCPKG Port Update 16. Git pull a local repository of VCPKG to `d:\vcpkg` in sync with the `main` branch of the VCPKG repository. 17. Run the PowerShell script `build\updatevcpkg.ps1` to update the DirectXTK12 port in VCPKG with the new release version. This will edit the files in `ports\directxtk12`. -18. Test the VCPKG port using all appropriate triplets and features. -19. Run `.\vcpkg --x-add-version directxtk12` to update the VCPKG versioning history. +18. Test the VCPKG port using the script at `assets/vcpkgdxtk12.cmd` (in this skill folder). Copy it to `d:\vcpkg` and run from there after bootstrapping VCPKG. +19. Run `.\vcpkg x-add-version directxtk12` to update the VCPKG versioning history. 20. Submit a PR to the VCPKG repository to update the DirectXTK12 port back to the main GitHub repo. The PR will be reviewed and merged by the VCPKG maintainers. ### Phase 7: Finalize diff --git a/.github/skills/release/assets/vcpkgdxtk12.cmd b/.github/skills/release/assets/vcpkgdxtk12.cmd new file mode 100644 index 00000000..87a4e4ce --- /dev/null +++ b/.github/skills/release/assets/vcpkgdxtk12.cmd @@ -0,0 +1,179 @@ +@set VCPKG_BINARY_SOURCES=clear +@set VCPKG_ROOT=%cd% +@if %1.==xbox. goto xbox +@if %1.==clang. goto clang +.\vcpkg install directxtk12[core]:x86-windows +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2-9]:x86-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x86-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xinput]:x86-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[spectre]:x86-windows-static-md --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x86-windows-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x86-windows-static-md +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x86-windows-static-md --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[core]:x64-windows +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2-9]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xinput]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[gameinput]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[spectre]:x64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-windows-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-windows-static-md +@if errorlevel 1 goto error +.\vcpkg install directxtk12[gameinput]:x64-windows-static-md --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x64-windows-static-md --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[core]:arm64-windows +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:arm64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xinput]:arm64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:arm64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[spectre]:arm64-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:arm64-windows-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:arm64-windows-static-md +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:arm64-windows-static-md --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[core]:arm64ec-windows +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:arm64ec-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:arm64ec-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[spectre]:arm64ec-windows --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x86-uwp +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-uwp +@if errorlevel 1 goto error +.\vcpkg install directxtk12:arm64-uwp +@if errorlevel 1 goto error +@where /Q x86_64-w64-mingw32-g++.exe +@if errorlevel 1 goto skipgcc64 +.\vcpkg install directxtk12:x64-mingw-dynamic +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x64-mingw-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[gameinput]:x64-mingw-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:x64-mingw-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-mingw-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x64-mingw-static --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xinput]:x64-mingw-static --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[gameinput]:x64-mingw-static --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:x64-mingw-static --recurse +@if errorlevel 1 goto error +:skipgcc64 +@where /Q i686-w64-mingw32-g++.exe +@if errorlevel 1 goto skipgcc32 +.\vcpkg install directxtk12:x86-mingw-dynamic +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x86-mingw-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xinput]:x86-mingw-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x86-mingw-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x86-mingw-static --recurse +@if errorlevel 1 goto error +:skipgcc32 +goto finish +:xbox +.\vcpkg install directxtk12:x64-xbox-scarlett +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-xbox-scarlett-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-xbox-xboxone +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-xbox-xboxone-static +@if errorlevel 1 goto error +@goto finish +:clang +.\vcpkg install directxtk12[core]:x64-clangcl-dynamic +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:x64-clangcl-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2-9]:x64-clangcl-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:x64-clangcl-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-clangcl-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12[core]:arm64-clangcl-dynamic +@if errorlevel 1 goto error +.\vcpkg install directxtk12[tools]:arm64-clangcl-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12[xaudio2redist]:arm64-clangcl-dynamic --recurse +@if errorlevel 1 goto error +.\vcpkg install directxtk12:arm64-clangcl-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-clangcl-uwp +@if errorlevel 1 goto error +.\vcpkg install directxtk12:arm64-clangcl-uwp +@if errorlevel 1 goto error +@if "%GXDKLatest%."=="." goto finish +.\vcpkg install directxtk12:x64-clangcl-scarlett +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-clangcl-scarlett-static +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-clangcl-xboxone +@if errorlevel 1 goto error +.\vcpkg install directxtk12:x64-clangcl-xboxone-static +@if errorlevel 1 goto error +:finish +@echo SUCCEEDED +@if %1.==xbox. goto eof +@if %1.==clang. goto eof +@where /Q x86_64-w64-mingw32-g++.exe +@if NOT errorlevel 1 goto gcc64 +@echo . +@echo . Run for MinGW64 +@echo . .\vcpkg install directxtk12:x64-mingw-dynamic +@echo . .\vcpkg install directxtk12[xaudio2redist]:x64-mingw-dynamic --recurse +@echo . .\vcpkg install directxtk12[gameinput]:x64-mingw-dynamic --recurse +@echo . .\vcpkg install directxtk12[tools]:x64-mingw-dynamic --recurse +@echo . .\vcpkg install directxtk12:x64-mingw-static +@echo . .\vcpkg install directxtk12[xaudio2redist]:x64-mingw-static --recurse +@echo . .\vcpkg install directxtk12[gameinput]:x64-mingw-static --recurse +@echo . .\vcpkg install directxtk12[tools]:x64-mingw-static --recurse +:gcc64 +@where /Q i686-w64-mingw32-g++.exe +@if NOT errorlevel 1 goto gcc32 +@echo . +@echo . Run for MinGW32 +@echo . .\vcpkg install directxtk12:x86-mingw-dynamic +@echo . .\vcpkg install directxtk12[xaudio2redist]:x86-mingw-dynamic --recurse +@echo . .\vcpkg install directxtk12:x86-mingw-static +@echo . .\vcpkg install directxtk12[xaudio2redist]:x86-mingw-static --recurse +:gcc32 +@goto eof +:error +@echo FAILED +:eof From 630f6ebadef621ed4b6597528a71eceba657f34e Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 2 Jun 2026 22:01:31 -0700 Subject: [PATCH 04/11] Code review --- .github/skills/release/SKILL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/skills/release/SKILL.md b/.github/skills/release/SKILL.md index fab7baa9..51234769 100644 --- a/.github/skills/release/SKILL.md +++ b/.github/skills/release/SKILL.md @@ -65,5 +65,6 @@ When fully completed, be sure to update the GitHub release with links to the mat | --- | --- | | `build\preparerelease.ps1` | Creates topic branch, updates version numbers and changelog stub | | `build\completerelease.ps1` | Sets tags, creates GitHub release from changelog | -| `build\promotenuget.ps1 -Release` | Promotes NuGet package to Release view on ADO feed | +| `build\promotenuget.ps1` | Promotes NuGet package to Release view on ADO feed | +| `assets\vcpkgdxtk12.cmd` | Tests VCPKG port across all triplets and features | | `build\updatevcpkg.ps1` | Updates DirectXTK12 VCPKG port files | From 235fdd322360fc9ae76001373fc060de90900512 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 2 Jun 2026 23:50:11 -0700 Subject: [PATCH 05/11] Feedabck --- .github/skills/directxtk12-usage/SKILL.md | 260 ++++++++++++++++++ .../directxtk12-usage/reference/overview.md | 176 ++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 .github/skills/directxtk12-usage/SKILL.md create mode 100644 .github/skills/directxtk12-usage/reference/overview.md diff --git a/.github/skills/directxtk12-usage/SKILL.md b/.github/skills/directxtk12-usage/SKILL.md new file mode 100644 index 00000000..e7c63761 --- /dev/null +++ b/.github/skills/directxtk12-usage/SKILL.md @@ -0,0 +1,260 @@ +--- +name: directxtk12-usage +description: Guide for integrating DirectX Tool Kit for DirectX 12 into new projects and understanding the library's API surface. Use this skill when asked about how to use DirectXTK12, set up a new project, or get an overview of available classes and functionality. +--- + +# DirectX Tool Kit for DirectX 12 — Usage Guide + +## Overview + +The *DirectX Tool Kit for DirectX 12* (DirectXTK12) is a collection of helper classes for writing Direct3D 12 C++ code for Win32 desktop applications (Windows 10+), Xbox Series X|S, Xbox One, and Universal Windows Platform (UWP) apps. + +- **Repository**: +- **Documentation**: +- **NuGet Packages**: `directxtk12_desktop_win10`, `directxtk12_uwp` +- **vcpkg Port**: `directxtk12` + +## Integration Methods + +### vcpkg manifest-mode (Recommended) + +In your `vcpkg.json` file, add the following: + +```json +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "directx-headers", + "directxmath", + "directxtk12" + ] +} +``` + +If using GameInput for the game input functionality, add the following: + +```json +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "directx-headers", + "directxmath", + { + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput" + ] + } + ] +} +``` + +If using DirectX Tool Kit for Audio and GameInput, add the following: + +```json +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "directx-headers", + "directxmath", + { + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput", + "xaudio2-9" + ] + } + ] +} +``` + +### vcpkg (classic) + +```bash +vcpkg install directxtk12 +``` + +Features: `xaudio2-9` (DirectX Tool Kit for Audio using XAudio 2.9), `gameinput` (Using GameInput for gamepad, keyboard, and mouse), `tools` (command-line tools). Triplets: `x64-windows`, `arm64-windows`, etc. + +For DLL usage (`x64-windows` default triplet), define `DIRECTX_TOOLKIT_IMPORT` in your consuming project. For static library usage, use `-static-md` triplet variants. + +CMakeLists.txt: + +```cmake +find_package(directxtk12 CONFIG REQUIRED) +target_link_libraries(your_target PRIVATE Microsoft::DirectXTK12) +``` + +Use the [d3d12game_vcpkg](https://github.com/walbourn/directx-vs-templates/tree/main/d3d12game_vcpkg) template as a starting point. + +### NuGet + +Use `directxtk12_desktop_win10` for Win32 desktop applications or `directxtk12_uwp` for UWP apps. + +### Project Reference + +Add the appropriate `.vcxproj` from the `DirectXTK12/` folder to your solution and add a project reference. Add the `DirectXTK12\Inc` directory to your Additional Include Directories. + +## Minimum Requirements + +- Windows 10 May 2020 Update SDK (19041) or later +- Visual Studio 2022, Visual Studio 2026, clang for Windows v12+, or MinGW 12.2 +- Direct3D Feature Level 11.0 or higher + +## Getting Started + +For a full step-by-step walkthrough, see the [Getting Started](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) tutorial on the wiki. + +A minimal initialization sequence: + +1. Create a `ID3D12Device`. +2. Create a `GraphicsMemory` instance (one per device). +3. Create a `DescriptorHeap` for SRV/CBV/UAV descriptors. +4. Use `ResourceUploadBatch` to upload textures and static buffers to the GPU. +5. Create rendering helpers (e.g., `SpriteBatch`, `Effects`, `Model`) with the appropriate pipeline state. +6. Each frame, call `GraphicsMemory::Commit` after executing command lists. + +## API Reference + +The public API is defined in the header files in the `Inc/` directory. See the [reference overview](reference/overview.md) for a categorized summary of all classes and helpers. + +Full documentation for each class is available on the [GitHub wiki](https://github.com/microsoft/DirectXTK12/wiki). + +API signatures are defined in the public headers under the `Inc/` directory. Always consult those headers for the authoritative function signatures, parameters, and SAL annotations. + +## Key Concepts + +### Resource Ownership + +DirectXTK12 classes follow RAII principles. Most objects are created with `std::make_unique` and destroyed automatically. COM resources are managed with `Microsoft::WRL::ComPtr`. + +### Device-Dependent vs Device-Independent + +Most DirectXTK12 objects are **device-dependent** — they are created with a `ID3D12Device*` and must be recreated if the device is lost. Plan your resource management accordingly. + +### Thread Safety + +DirectXTK12 rendering classes (SpriteBatch, Effects, PrimitiveBatch, etc.) are **not** thread-safe. Use one instance per thread, or synchronize access externally. Resource creation (texture loading, model loading) can be done from any thread. + +## Key Concepts for DirectX 12 Users + +- **Pipeline State Objects (PSOs)**: Unlike the DX11 version, DX12 requires explicit PSO management. Use `EffectPipelineStateDescription` and `RenderTargetState` to configure PSOs for effects and rendering helpers. +- **Descriptor Heaps**: Use `DescriptorHeap` to manage shader-visible descriptor heaps. Most rendering classes require descriptor heap indices at draw time. +- **Resource Upload**: GPU resources must be uploaded explicitly. `ResourceUploadBatch` batches uploads into a single command list for efficiency. +- **Graphics Memory**: `GraphicsMemory` manages per-frame dynamic allocations (constant buffers, dynamic vertex/index buffers). Call `Commit` once per frame. + +## Namespace + +All classes and functions reside in the `DirectX` namespace. Headers that contain Direct3D 12-specific types use `inline namespace DX12` to avoid conflicts when both DX11 and DX12 toolkits are linked together. + +```cpp +#include "SpriteBatch.h" + +// Usage: +auto spriteBatch = std::make_unique(device, ...); +``` + +## Common Patterns + +### Creating an Effect + +```cpp +#include "Effects.h" +#include "EffectPipelineStateDescription.h" +#include "RenderTargetState.h" + +RenderTargetState rtState(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT); + +EffectPipelineStateDescription pd( + &VertexPositionNormalTexture::InputLayout, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullCounterClockwise, + rtState); + +auto effect = std::make_unique(device, EffectFlags::Lighting | EffectFlags::Texture, pd); +``` + +### Loading and Drawing a Model + +```cpp +#include "Model.h" + +auto model = Model::CreateFromSDKMESH(device, L"mymodel.sdkmesh"); + +// Upload resources +ResourceUploadBatch upload(device); +upload.Begin(); +model->LoadStaticBuffers(device, upload); +upload.End(commandQueue).wait(); + +// Draw (simplified — see wiki for full parameter details) +model->Draw(commandList, ...); +``` + +### Texture Loading + +```cpp +#include "DDSTextureLoader.h" +#include "ResourceUploadBatch.h" +#include "DescriptorHeap.h" + +ResourceUploadBatch upload(device); +upload.Begin(); + +Microsoft::WRL::ComPtr texture; +CreateDDSTextureFromFile(device, upload, L"texture.dds", texture.ReleaseAndGetAddressOf()); + +upload.End(commandQueue).wait(); +``` + +### Input Handling + +```cpp +#include "Keyboard.h" +#include "Mouse.h" +#include "GamePad.h" + +auto keyboard = std::make_unique(); +auto mouse = std::make_unique(); +auto gamePad = std::make_unique(); + +// In update loop +auto kb = keyboard->GetState(); +if (kb.Escape) + PostQuitMessage(0); + +auto pad = gamePad->GetState(0); +if (pad.IsConnected()) +{ + if (pad.IsAPressed()) + /* jump */; +} +``` + +### Audio + +```cpp +#include "Audio.h" + +// Create audio engine +auto audioEngine = std::make_unique(); + +// Load and play a sound +auto soundEffect = std::make_unique(audioEngine.get(), L"explosion.wav"); +soundEffect->Play(); + +// Per-frame update +audioEngine->Update(); +``` + +> **Note**: Code examples above are simplified for clarity. Consult the [wiki tutorials](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) and public headers in `Inc/` for complete working code with all required parameters. + +## Further Reading + +- [DirectXTK Wiki](https://github.com/microsoft/DirectXTK12/wiki) +- [DirectX Tool Kit for Audio](https://github.com/Microsoft/DirectXTK/wiki/Audio) +- [SimpleMath documentation](https://github.com/Microsoft/DirectXTK/wiki/SimpleMath) +- [Project templates](https://github.com/walbourn/directx-vs-templates/tree/main/d3d12game_vcpkg) diff --git a/.github/skills/directxtk12-usage/reference/overview.md b/.github/skills/directxtk12-usage/reference/overview.md new file mode 100644 index 00000000..2190bc89 --- /dev/null +++ b/.github/skills/directxtk12-usage/reference/overview.md @@ -0,0 +1,176 @@ +# API Reference Overview + +This document provides a high-level overview of the DirectX Tool Kit for DirectX 12 public API. For authoritative function signatures, parameters, and SAL annotations, consult the public headers in the `Inc/` directory. + +For detailed documentation on each class, see the [DirectXTK12 Wiki](https://github.com/microsoft/DirectXTK12/wiki). + +## Resource Management + +### GraphicsMemory (`Inc/GraphicsMemory.h`) + +Manages per-frame dynamic graphics memory allocation for constant buffers, dynamic vertex buffers, and dynamic index buffers. One instance should be created per `ID3D12Device`. + +- Call `Commit` once per frame after executing command lists to reclaim memory from completed frames. +- Provides `GraphicsResource` for sub-allocated memory regions. + +### ResourceUploadBatch (`Inc/ResourceUploadBatch.h`) + +Batches GPU resource uploads (textures, static buffers) into a single command list for efficient submission. + +- Call `Begin` to start recording uploads. +- Call `End` to submit the upload command list; returns a future to wait on. +- Supports automatic mipmap generation during upload. + +### DescriptorHeap (`Inc/DescriptorHeap.h`) + +Helper for creating and managing Direct3D 12 descriptor heaps (SRV/CBV/UAV, Sampler, RTV, DSV). + +- Simplifies index-based descriptor allocation. +- Provides CPU and GPU handle accessors by index. + +### BufferHelpers (`Inc/BufferHelpers.h`) + +Free functions for creating static and constant buffers from CPU data. + +- `CreateStaticBuffer` — uploads vertex/index/structured buffer data. +- `CreateTextureFromMemory` — creates a texture resource from in-memory data. + +### DirectXHelpers (`Inc/DirectXHelpers.h`) + +Miscellaneous utility functions for Direct3D 12 programming. + +- Resource barrier helpers. +- Shader resource view creation helpers. + +## Pipeline State + +### RenderTargetState (`Inc/RenderTargetState.h`) + +A lightweight struct that communicates render target format and sample count information needed when creating PSOs. + +### EffectPipelineStateDescription (`Inc/EffectPipelineStateDescription.h`) + +Bundles input layout, blend state, depth-stencil state, rasterizer state, and render target state into a single description used by effect constructors to create PSOs. + +## Rendering + +| Header | Classes / Functions | Purpose | +| --- | --- | --- | +| `SpriteBatch.h` | `SpriteBatch` | Hardware-accelerated 2D sprite rendering with batching, rotation, and scaling. | +| `SpriteFont.h` | `SpriteFont` | Bitmap font rendering using SpriteBatch. Supports MakeSpriteFont and BMFont formats. | +| `PrimitiveBatch.h` | `PrimitiveBatch` | Low-level immediate-mode rendering of user-defined vertex types. | +| `GeometricPrimitive.h` | `GeometricPrimitive` | Factory for common 3D shapes (sphere, cube, cylinder, torus, teapot, etc.). | +| `Model.h` | `Model`, `ModelMesh`, `ModelMeshPart`, `ModelBone` | Loading and rendering of 3D models from CMO, SDKMESH and VBO file formats. | + +> Model requires RTTI (`/GR`) to be enabled. + +## Effects (Shaders) + +| Header | Classes | Purpose | +| --- | --- | --- | +| `Effects.h` | `BasicEffect` | Per-pixel lighting with texture, vertex color, and fog support. | +| | `AlphaTestEffect` | Alpha testing (clip pixels below a threshold). | +| | `DualTextureEffect` | Two-layer multitexture blending (e.g., lightmaps). | +| | `EnvironmentMapEffect` | Cubic environment map reflections. | +| | `SkinnedEffect` | Vertex skinning with up to 72 bones. | +| | `SkinnedNormalMapEffect` | Skinned rendering with normal maps. | +| | `NormalMapEffect` | Normal map and optional specular map rendering. | +| | `PBREffect` | Physically-based rendering (metalness/roughness workflow). | +| | `SkinnedPBREffect` | PBR with vertex skinning. | +| | `DebugEffect` | Diagnostic visualization (normals, tangents, texture coordinates). | +| | `IEffect`, `IEffectMatrices`, `IEffectLights`, `IEffectFog`, `IEffectSkinning` | Interfaces implemented by effects. | +| | `IEffectFactory`, `EffectFactory`, `PBREffectFactory` | Model-driven effect creation and caching. | +| | `IEffectTextureFactory`, `EffectTextureFactory` | Texture loading and caching for models. | + +Effects are constructed with an `EffectFlags` bitmask and an `EffectPipelineStateDescription`. Each instance of an effect internally creates a ID3D12PipelineState object, so is immutable after creation. + +## Textures + +| Header | Functions | Purpose | +| --- | --- | --- | +| `DDSTextureLoader.h` | `CreateDDSTextureFromFile`, `CreateDDSTextureFromMemory` | Load DDS textures (supports all D3D12 formats, mipmaps, cubemaps, arrays). | +| `WICTextureLoader.h` | `CreateWICTextureFromFile`, `CreateWICTextureFromMemory` | Load common image formats (PNG, JPEG, BMP, TIFF, GIF) via WIC. | +| `XboxDDSTextureLoader.h` | `CreateDDSTextureFromFile`, `CreateDDSTextureFromMemory` | Xbox-optimized DDS loader for tiled resources. | +| `ScreenGrab.h` | `SaveDDSTextureToFile`, `SaveWICTextureToFile` | Capture render targets to DDS or WIC image files. | + +## States and Helpers + +| Header | Classes / Functions | Purpose | +| --- | --- | --- | +| `CommonStates.h` | `CommonStates` | Pre-built blend, depth-stencil, rasterizer, and sampler state objects. | +| `DirectXHelpers.h` | `CreateInputLayoutFromEffect`, `SetDebugObjectName` | Utility functions for input layouts, debug naming, and resource manipulation. | +| `BufferHelpers.h` | `CreateStaticBuffer`, `CreateTextureFromMemory` | Helper functions for creating D3D12 buffers and textures. | +| `GraphicsMemory.h` | `GraphicsMemory` | Per-frame memory management for dynamic resources. | +| `VertexTypes.h` | `VertexPosition`, `VertexPositionColor`, `VertexPositionTexture`, `VertexPositionNormal`, `VertexPositionNormalTexture`, `VertexPositionNormalColor`, `VertexPositionNormalColorTexture`, `VertexPositionNormalTangentColorTexture`, `VertexPositionNormalTangentColorTextureSkinning` | Pre-defined vertex structure types compatible with the built-in effects provided with `D3D12_INPUT_LAYOUT_DESC`. | + +## Post-Processing + +| Header | Classes | Purpose | +| --- | --- | --- | +| `PostProcess.h` | `IPostProcess` | Base interface for post-processing effects. | +| | `BasicPostProcess` | Copy, monochrome, sepia, down-scale, bloom extract/blur. | +| | `DualPostProcess` | Merge/blend two textures (bloom combine, weighted average). | +| | `ToneMapPostProcess` | HDR tone mapping (Reinhard, ACESFilmic, etc.) and OETF curves. | + +## Input + +| Header | Classes | Purpose | +| --- | --- | --- | +| `Keyboard.h` | `Keyboard`, `Keyboard::State`, `Keyboard::KeyboardStateTracker` | Keyboard state polling and key-press/release tracking. | +| `Mouse.h` | `Mouse`, `Mouse::State`, `Mouse::ButtonStateTracker` | Mouse state polling with absolute and relative modes. | +| `GamePad.h` | `GamePad`, `GamePad::State`, `GamePad::ButtonStateTracker` | Gamepad state polling, vibration, and button tracking. Supports GameInput, XInput, and Windows.Gaming.Input backends. | + +See [DirectX Tool Kit wiki: GamePad](https://github.com/Microsoft/DirectXTK/wiki/GamePad), [DirectX Tool Kit wiki: Keyboard](https://github.com/Microsoft/DirectXTK/wiki/Keyboard), and [DirectX Tool Kit wiki: Mouse](https://github.com/Microsoft/DirectXTK/wiki/Mouse) for full documentation. + +## Audio + +| Header | Classes | Purpose | +| --- | --- | --- | +| `Audio.h` | `AudioEngine` | XAudio2-based audio engine with 3D audio, mastering voice, and device management. | +| | `SoundEffect` | Loads WAV files and XACT-style wave banks for playback. | +| | `SoundEffectInstance` | Controls playback of a sound (play, pause, stop, loop, volume, pitch, pan). | +| | `SoundStreamInstance` | Streaming playback from disk for large audio files. | +| | `WaveBank` | Loads XACT-style wave bank (.xwb) files containing multiple sounds. | +| | `DynamicSoundEffectInstance` | Programmatic audio generation via callback-driven buffer submission. | +| | `AudioListener`, `AudioEmitter` | 3D audio positioning for spatialized sound. | + + +See the [DirectX Tool Kit for Audio wiki](https://github.com/Microsoft/DirectXTK/wiki/Audio) for full documentation. + +## Math + +| Header | Classes / Types | Purpose | +| --- | --- | --- | +| `SimpleMath.h` | `Vector2`, `Vector3`, `Vector4`, `Matrix`, `Quaternion`, `Plane`, `Color`, `Ray`, `Viewport`, `Rectangle` | Wrapper types around DirectXMath (XMFLOAT/XMVECTOR) providing operator overloads and convenience methods. | + +All types support standard arithmetic operators and implicit conversion to/from DirectXMath SIMD types (`XMVECTOR`, `XMMATRIX`). + +See the [SimpleMath wiki](https://github.com/Microsoft/DirectXTK/wiki/SimpleMath) for full documentation. + +## Header Inclusion + +All public headers are standalone — include only what you need: + +```cpp +#include "SpriteBatch.h" // For 2D sprite rendering +#include "Effects.h" // For shader effects +#include "Model.h" // For 3D model loading +#include "Audio.h" // For audio playback +#include "SimpleMath.h" // For math helper types +``` + +There is no single umbrella header. Each header declares its dependencies via forward declarations or includes as needed. + +### VCPKG Usage + +When using VCPKG with MSBuild integration (both classic and manifest mode), the public headers must be included with a `directxtk12/` prefix. + +```cpp +#include "directxtk12/SpriteBatch.h" +#include "directxtk12/Effects.h" +#include "directxtk12/Model.h" +#include "directxtk12/Audio.h" +#include "directxtk12/SimpleMath.h" +``` + +When using VCPKG with CMake integration via `find_package`, the include path is added directly so the prefix is not required, but will generally work as well. From 4c27f4b86c8e817e9ddcf31519514107ce77782c Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 3 Jun 2026 00:09:41 -0700 Subject: [PATCH 06/11] Pick markdown lint --- .github/skills/directxtk12-usage/reference/overview.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/skills/directxtk12-usage/reference/overview.md b/.github/skills/directxtk12-usage/reference/overview.md index 2190bc89..30af321b 100644 --- a/.github/skills/directxtk12-usage/reference/overview.md +++ b/.github/skills/directxtk12-usage/reference/overview.md @@ -134,7 +134,6 @@ See [DirectX Tool Kit wiki: GamePad](https://github.com/Microsoft/DirectXTK/wiki | | `DynamicSoundEffectInstance` | Programmatic audio generation via callback-driven buffer submission. | | | `AudioListener`, `AudioEmitter` | 3D audio positioning for spatialized sound. | - See the [DirectX Tool Kit for Audio wiki](https://github.com/Microsoft/DirectXTK/wiki/Audio) for full documentation. ## Math From d445c7b6bc2106b4ec431cfefab3aabf8a5b70c3 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 4 Jun 2026 11:17:26 -0700 Subject: [PATCH 07/11] Move usage skill to public location --- .github/copilot-instructions.md | 1 + README.md | 4 ++++ {.github/skills => skills}/directxtk12-usage/SKILL.md | 0 .../skills => skills}/directxtk12-usage/reference/overview.md | 0 4 files changed, 5 insertions(+) rename {.github/skills => skills}/directxtk12-usage/SKILL.md (100%) rename {.github/skills => skills}/directxtk12-usage/reference/overview.md (100%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 98792ca0..2b08ebe0 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -42,6 +42,7 @@ Audio/ # DirectX Tool Kit for Audio implementation files. Inc/ # Public header files. Src/ # Implementation header and source files. Shaders/ # HLSL shader files. +skills/ # Published CoPilot skills for use by developers. Tests/ # Tests are designed to be cloned from a separate repository at this location. wiki/ # Local clone of the GitHub wiki documentation repository. ``` diff --git a/README.md b/README.md index 0b05ce7f..a8001667 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,10 @@ These components are designed to work without requiring any content from the leg * Contains miscellaneous build files and scripts. +* ``skills\`` + + * Contains published CoPilot skills for use by developers. + > MakeSpriteFont and XWBTool can be found in the [DirectX Tool Kit for DirectX 11](https://github.com/microsoft/DirectXTK). Audio, GamePad, Keyboard, Mouse, and SimpleMath are identical between both versions of the toolkit. ## Documentation diff --git a/.github/skills/directxtk12-usage/SKILL.md b/skills/directxtk12-usage/SKILL.md similarity index 100% rename from .github/skills/directxtk12-usage/SKILL.md rename to skills/directxtk12-usage/SKILL.md diff --git a/.github/skills/directxtk12-usage/reference/overview.md b/skills/directxtk12-usage/reference/overview.md similarity index 100% rename from .github/skills/directxtk12-usage/reference/overview.md rename to skills/directxtk12-usage/reference/overview.md From ae6b8e8a63382b9f00aa61a0f1cd35c9578a6956 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 4 Jun 2026 11:42:19 -0700 Subject: [PATCH 08/11] Update readme --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a8001667..d6d2d2e1 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ These components are designed to work without requiring any content from the leg * ``skills\`` - * Contains published CoPilot skills for use by developers. + * Contains published CoPilot skills for use by developers. > MakeSpriteFont and XWBTool can be found in the [DirectX Tool Kit for DirectX 11](https://github.com/microsoft/DirectXTK). Audio, GamePad, Keyboard, Mouse, and SimpleMath are identical between both versions of the toolkit. @@ -68,6 +68,18 @@ These components are designed to work without requiring any content from the leg Documentation is available on the [GitHub wiki](https://github.com/Microsoft/DirectXTK12/wiki). +## CoPilot Usage + +For CoPilot CLI assistance with using DirectX Tool Kit, try: + +```bash +winget install GitHub.Copilot +winget install GitHub.cli +gh skill install microsoft/directxtk12 +copilot +/skills list +``` + ## Notices All content and source code for this package are subject to the terms of the [MIT License](https://github.com/microsoft/DirectXTK12/blob/main/LICENSE). From 48ee8adf79d7ccd7e041231b3c8bfae3cc937740 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 4 Jun 2026 21:59:36 -0700 Subject: [PATCH 09/11] Update YAML front-matter --- .github/copilot-instructions.md | 2 +- skills/directxtk12-usage/SKILL.md | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2b08ebe0..2b1cb3c4 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -33,7 +33,7 @@ These instructions define how GitHub Copilot should assist with this project. Th ## File Structure -```txt +```plaintext .azuredevops/ # Azure DevOps pipeline configuration and policy files. .github/ # GitHub Actions workflow files and linter configuration files. .nuget/ # NuGet package configuration files. diff --git a/skills/directxtk12-usage/SKILL.md b/skills/directxtk12-usage/SKILL.md index e7c63761..0235e105 100644 --- a/skills/directxtk12-usage/SKILL.md +++ b/skills/directxtk12-usage/SKILL.md @@ -1,6 +1,13 @@ --- name: directxtk12-usage -description: Guide for integrating DirectX Tool Kit for DirectX 12 into new projects and understanding the library's API surface. Use this skill when asked about how to use DirectXTK12, set up a new project, or get an overview of available classes and functionality. +description: >- + Guide for integrating DirectX Tool Kit for DirectX 12 into new projects and understanding the library's API surface. + Use this skill when asked about how to use DirectXTK12, set up a new project, or get an overview of + available classes and functionality. +license: MIT +metadata: + author: chuckw + version: "1.0" --- # DirectX Tool Kit for DirectX 12 — Usage Guide From f503e9476935cd4c679ade74c785a76018b88e81 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Fri, 5 Jun 2026 09:58:47 -0700 Subject: [PATCH 10/11] Add tutorial skill --- skills/directxtk12-tutorial/SKILL.md | 42 ++++ skills/directxtk12-tutorial/assets/cat.png | Bin 0 -> 15241 bytes .../assets/courier.spritefont | Bin 0 -> 62472 bytes .../reference/nextsteps.md | 68 ++++++ .../directxtk12-tutorial/reference/step0.md | 102 ++++++++ .../directxtk12-tutorial/reference/step1.md | 141 +++++++++++ .../directxtk12-tutorial/reference/step2.md | 128 ++++++++++ .../directxtk12-tutorial/reference/step3.md | 178 ++++++++++++++ .../directxtk12-tutorial/reference/step4.md | 214 +++++++++++++++++ .../directxtk12-tutorial/reference/step5.md | 122 ++++++++++ .../directxtk12-tutorial/reference/step6.md | 190 +++++++++++++++ .../directxtk12-tutorial/reference/step7.md | 224 ++++++++++++++++++ .../reference/tutorial-steps.md | 18 ++ 13 files changed, 1427 insertions(+) create mode 100644 skills/directxtk12-tutorial/SKILL.md create mode 100644 skills/directxtk12-tutorial/assets/cat.png create mode 100644 skills/directxtk12-tutorial/assets/courier.spritefont create mode 100644 skills/directxtk12-tutorial/reference/nextsteps.md create mode 100644 skills/directxtk12-tutorial/reference/step0.md create mode 100644 skills/directxtk12-tutorial/reference/step1.md create mode 100644 skills/directxtk12-tutorial/reference/step2.md create mode 100644 skills/directxtk12-tutorial/reference/step3.md create mode 100644 skills/directxtk12-tutorial/reference/step4.md create mode 100644 skills/directxtk12-tutorial/reference/step5.md create mode 100644 skills/directxtk12-tutorial/reference/step6.md create mode 100644 skills/directxtk12-tutorial/reference/step7.md create mode 100644 skills/directxtk12-tutorial/reference/tutorial-steps.md diff --git a/skills/directxtk12-tutorial/SKILL.md b/skills/directxtk12-tutorial/SKILL.md new file mode 100644 index 00000000..b9cc29e4 --- /dev/null +++ b/skills/directxtk12-tutorial/SKILL.md @@ -0,0 +1,42 @@ +--- +name: directxtk12-tutorial +description: >- + Walk through the DirectX Tool Kit for DirectX 12 Getting Started tutorial step by step. Use this skill when + asked to follow the tutorial, set up a new DirectX 12 project, or learn how to use DirectX Tool Kit for DX12 from scratch. +license: MIT +metadata: + author: chuckw + version: "1.0" +--- + +# DirectX Tool Kit for DirectX 12 — Getting Started Tutorial + +This skill walks the user through the [Getting Started](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) tutorial for DirectX Tool Kit for DirectX 12 step by step. + +Follow each step in order. Each step builds on the previous one. + +At the end of each step, **ask the user** if they would like to see the Technical Notes section (which provides a brief overview of the underlying Direct3D 12 APIs and objects used by the toolkit in that step) or skip it and move on to the next step. + +## Tutorial Steps + +| Step | Title | Reference | +| ------ | ------- | ----------- | +| 0 | Prerequisites | [reference/step0.md](reference/step0.md) | +| 1 | Project Setup | [reference/step1.md](reference/step1.md) | +| 2 | Building the Project | [reference/step2.md](reference/step2.md) | +| 3 | Adding DirectX Tool Kit | [reference/step3.md](reference/step3.md) | +| 4 | Sprites and Textures | [reference/step4.md](reference/step4.md) | +| 5 | Drawing Text | [reference/step5.md](reference/step5.md) | +| 6 | Simple Rendering | [reference/step6.md](reference/step6.md) | +| 7 | 3D Shapes | [reference/step7.md](reference/step7.md) | + +## Assets + +The `assets/` folder contains files needed during the tutorial: + +- `cat.png` — sprite texture used in Step 4 +- `courier.spritefont` — pre-built sprite font used in Step 5 + +## Full Tutorial Sequence + +See [reference/tutorial-steps.md](reference/tutorial-steps.md) for the complete list of planned tutorial lessons beyond these initial seven steps. diff --git a/skills/directxtk12-tutorial/assets/cat.png b/skills/directxtk12-tutorial/assets/cat.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e0e60f6a9a3631847444ee0181ee828ce42897 GIT binary patch literal 15241 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 Y#61}7y}!!~-T$Y(zJ9vfqhkI3KR{1LmH+?% literal 0 HcmV?d00001 diff --git a/skills/directxtk12-tutorial/reference/nextsteps.md b/skills/directxtk12-tutorial/reference/nextsteps.md new file mode 100644 index 00000000..42943e72 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/nextsteps.md @@ -0,0 +1,68 @@ +# Next Steps + +## Graphics + +To explore more about DirectX 12 Graphics functionality, continue with the tutorials at [Getting Started](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) starting at [Rendering a model](https://github.com/microsoft/DirectXTK12/wiki/Rendering-a-model). + +## Input + +To implement game input using GamePad, see [Game controller input](https://github.com/microsoft/DirectXTK/wiki/Game-controller-input) which for this tutorial's project will use the GameInput APIs. + +To implement game input using Mouse and Keyboard, see [Mouse and keyboard input](https://github.com/microsoft/DirectXTK/wiki/Mouse-and-keyboard-input). + +## Math + +For more on the SimpleMath library, which is a C++ wrapper for the DirectXMath SIMD library, see [Using the SimpleMath library](https://github.com/microsoft/DirectXTK/wiki/Using-the-SimpleMath-library). + +Alternatively, advanced users can use the **directxmath-usage** skill from [DirectXMath](https://github.com/microsoft/DirectXMath). + +## DirectX Tool Kit for Audio + +The audio functionality is built on XAudio2 which is a game audio API for Windows which provides real-time mixing and audio processing capabilities. + +To add *DirectX Tool Kit for Audio* to your project, update the `vcpkg.json` file: + +```json +{ + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput", + "xaudio2-9" + ] +} +``` + +For example, the full `vcpkg.json` should look something like: + +```json +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + { + "name": "directx-dxc", + "host": true + }, + "directx-dxc", + "directx-headers", + "directx12-agility", + "directxmath", + { + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput", + "xaudio2-9" + ] + } + ] +} +``` + +Then add to the pch.h: + +```cpp +#include +``` + +From there, pick up at [Adding audio to your project](https://github.com/microsoft/DirectXTK/wiki/Adding-audio-to-your-project). diff --git a/skills/directxtk12-tutorial/reference/step0.md b/skills/directxtk12-tutorial/reference/step0.md new file mode 100644 index 00000000..ee08d5a0 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step0.md @@ -0,0 +1,102 @@ +# Step 0: Prerequisites + +Before starting the tutorial, verify the user has the necessary tools and environment set up. + +**Ask the user:** Have you already installed the tools below, or would you like help checking? + +## Required Software + +| Tool | Minimum Version | Purpose | +| ------ | ----------------- | --------- | +| **Visual Studio 2022** or **Visual Studio 2026** | 17.4+ / any | IDE and C++ compiler | +| **Desktop development with C++** workload | — | Includes MSVC toolset, Windows SDK, and CMake tools | +| **VCPKG component** (`Microsoft.VisualStudio.Component.Vcpkg`) | — | Package manager integration for dependencies | +| **Windows SDK** | 10.0.22000.0+ (Windows 11) | DirectX 12 headers and libraries | +| **Git** | any | Clone templates and manage source control | + +> Visual Studio Community edition is sufficient. The **VCPKG component** is included in the "Desktop development with C++" workload by default in VS 2022 17.7+ and VS 2026. + +## Hardware Requirements + +- A **Direct3D 12-capable GPU** (Feature Level 11.0 or higher) is required. +- All modern dedicated GPUs from NVIDIA, AMD, and Intel support Direct3D 12. +- Alternatively, the **WARP software adapter** can be used for development without dedicated GPU hardware (debug builds use this as a fallback). + +## Optional but Recommended + +| Tool | Purpose | +| ------ | --------- | +| **CMake** (3.21+) | Required only if creating a CMake project instead of MSBuild | +| **Windows Terminal** | Better terminal experience for PowerShell commands | +| **PIX on Windows** | GPU debugging and profiling for Direct3D 12 | + +## Verification Steps + +Run the following checks in a PowerShell terminal to confirm the environment is ready: + +### Visual Studio + +```powershell +# Verify a VS 2022 or later install with the C++ Desktop workload +& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17.0," -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath +``` + +### Windows SDK + +```powershell +# Check for a Windows 10 SDK (10.0.19041.0 or later) +Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -ErrorAction SilentlyContinue | + Get-ItemProperty | Select-Object -ExpandProperty KitsRoot10 -ErrorAction SilentlyContinue +``` + +### VCPKG + +```powershell +# Verify the vcpkg component is present in the VS install +$vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17.0," -requires Microsoft.VisualStudio.Component.Vcpkg -property installationPath | Select-Object -First 1 +Test-Path "$vsPath\VC\vcpkg\vcpkg.exe" +``` + +### Git + +```powershell +git --version +``` + +### Direct3D 12 Support + +```powershell +# Check for a D3D12-capable adapter using dxdiag (quick check) +dxdiag /t "$env:TEMP\dxdiag.txt"; Start-Sleep -Seconds 3 +Select-String -Path "$env:TEMP\dxdiag.txt" -Pattern "Feature Levels:.*12" +Remove-Item "$env:TEMP\dxdiag.txt" -ErrorAction SilentlyContinue +``` + +## Troubleshooting + +- **Missing VCPKG component** — Open the Visual Studio Installer, click **Modify**, and ensure the "Desktop development with C++" workload is checked. In the Individual Components tab, confirm `Microsoft.VisualStudio.Component.Vcpkg` is selected. +- **Windows SDK not found** — Install a Windows 10 SDK (10.0.19041.0 or later) through the Visual Studio Installer under Individual Components. +- **Git not found** — Install Git from or via `winget install Git.Git`. +- **No D3D12-capable GPU** — Ensure your GPU drivers are up to date. For development without a capable GPU, builds will fall back to the WARP software adapter in debug mode. + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +### Why vcpkg? + +The tutorial uses vcpkg in **manifest mode** to manage DirectX Tool Kit for DX12 as a dependency. This approach: + +1. **Pins dependency versions** via `vcpkg.json` and `vcpkg-configuration.json`, ensuring reproducible builds. +2. **Avoids manual library setup** — no need to download, build, or configure include/library paths yourself. +3. **Supports multiple configurations** — vcpkg handles Debug/Release and x64/ARM64 builds through triplets. + +### DirectX 12 and Windows + +Direct3D 12 is available on Windows 10 and Windows 11 (all editions). The Windows SDK provides the `d3d12.h`, `dxgi1_4.h`, and related headers. No separate DirectX SDK download is required — the legacy standalone DirectX SDK (June 2010) is not needed for this tutorial. + +### Direct3D 12 vs. Direct3D 11 + +Direct3D 12 is a lower-level API compared to Direct3D 11. It provides more explicit control over GPU resources, memory management, and synchronization. The DirectX Tool Kit for DX12 provides a higher-level abstraction that makes it easier to use Direct3D 12, handling descriptor heaps, resource barriers, and command list management for you. + +> For more background on the modern Windows SDK vs. the legacy DirectX SDK, see [this blog post](https://walbourn.github.io/where-is-the-directx-sdk-2024-edition/). diff --git a/skills/directxtk12-tutorial/reference/step1.md b/skills/directxtk12-tutorial/reference/step1.md new file mode 100644 index 00000000..d86eb065 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step1.md @@ -0,0 +1,141 @@ +# Step 1: Project Setup + +First, determine if the user needs a new project or already has one. + +**Ask the user:** Do you want to create a new project, or do you already have an existing Direct3D 12 project? + +## Creating a New Project + +If the user wants a new project, use the `d3d12game_vcpkg` template from . + +**Ask the user:** + +1. What project name would you like? (Default: `Direct3DGame`) +2. Do you want an MSBuild (.vcxproj) project or a CMake project (CMake recommended)? +3. Where should the project be created? (Default: `$Env:USERPROFILE\source`) + +Then download the templates from the latest GitHub release and run the appropriate script: + +```powershell +# Download and extract the templates repo from the latest release +$release = (Invoke-RestMethod -Uri "https://api.github.com/repos/walbourn/directx-vs-templates/releases/latest").tag_name +$templatesZip = "$env:TEMP\directx-vs-templates.zip" +$templatesDir = "$env:TEMP\directx-vs-templates" +Invoke-WebRequest -Uri "https://github.com/walbourn/directx-vs-templates/archive/refs/tags/$release.zip" -OutFile $templatesZip +Expand-Archive -Path $templatesZip -DestinationPath $templatesDir -Force +$repoRoot = Get-ChildItem -Path $templatesDir -Directory | Select-Object -First 1 +``` + +### MSBuild + +```powershell +& "$($repoRoot.FullName)\VSIX\createmsbuild.ps1" d3d12game_vcpkg +``` + +Parameters: +- `TemplateDir`: Use `d3d12game_vcpkg` for the DirectX 12 game template with vcpkg integration. +- `ProjectName`: The project name (default: `Direct3DGame`). Used for the `.vcxproj` filename and solution. +- `TargetDir`: Output directory (default: `$Env:USERPROFILE\source`). A subdirectory named `` is created here. +- `PlatformToolset`: VS platform toolset (default: `v143` for VS 2022, use `v144` for VS 2026). + +### CMake + +```powershell +& "$($repoRoot.FullName)\VSIX\createcmake.ps1" d3d12game_vcpkg +``` + +Parameters: +- `TemplateDir`: Use `d3d12game_vcpkg` for the DirectX 12 game template with vcpkg integration. +- `ProjectName`: The project name (default: `Direct3DGame`). Used for the CMake project name. +- `TargetDir`: Output directory (default: `$Env:USERPROFILE\source`). A subdirectory named `` is created here. + +### Cleanup + +After the project is created, clean up the temp files: + +```powershell +Remove-Item -Path $templatesZip -Force +Remove-Item -Path $templatesDir -Recurse -Force +``` + +### Note for git repositories + +If the project is being created in a git repository, then the `.gitignore` file at the root of the repository should be updated to exclude the vcpkg installed files and build artifacts. + +```plaintext +**/vcpkg_installed/ +``` + +## Using an Existing Project + +If the user already has a project, verify they have: + +1. A Direct3D 12 device and command queue +2. A render loop with SwapChain and Present +3. A command list for rendering +4. DirectXTK12 integrated via vcpkg, NuGet, or project reference (see the **directxtk12-usage** skill for integration guidance) + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +The `d3d12game_vcpkg` template creates a minimal Direct3D 12 application with the following architecture: + +### Overview + +The basics of a Win32 Direct3D 12 application include: + +1. **Win32 window creation** — A window is created using the Win32 API. +2. **Direct3D 12 device initialization** — The DXGI API is used to enumerate adapters, and then an ID3D12Device object is created which is used for creating resources. Unlike Direct3D 11, there is no immediate context — instead, the application creates command lists and command queues to submit work to the GPU. +3. **Render loop** — For a game application, a loop is run to update the game state and render the scene each frame. Unlike in traditional applications, the game loop is real-time and continuous rather than waiting for user input. +4. **Swap chain management** — A IDXGISwapChain object is used to manage the presentation of rendered frames. If the application rendering gets too far ahead of the display, it will wait until more frames are fully processed. + +### Main.cpp — Application Entry Point + +- **Win32 window creation** — Registers a `WNDCLASSEX`, creates an `HWND` with `CreateWindowExW`, and runs a standard `PeekMessage` loop. When no messages are pending, `Game::Tick()` is called to drive the game loop. +- **Window message handling** — The `WndProc` handles resize (`WM_SIZE`), minimize/restore (suspend/resume), ALT+ENTER fullscreen toggle, display changes, and power management. +- **Hybrid GPU preference** — Exports `NvOptimusEnablement` and `AmdPowerXpressRequestHighPerformance` to prefer discrete GPUs on hybrid systems. +- **COM initialization** — Calls `CoInitializeEx` (multithreaded) which is required for WIC texture loading later. + +> For details on the fullscreen management, see [this blog post](https://walbourn.github.io/care-and-feeding-of-modern-swapchains/). + +### DeviceResources — Direct3D 12 Device Wrapper + +The `DeviceResources` class encapsulates all Direct3D 12 device and swap chain management: + +- **`IDXGIFactory6`** — Created via `CreateDXGIFactory2`. Used to enumerate adapters, create the swap chain, and check feature support (tearing, HDR, flip model). +- **`ID3D12Device`** — Created via `D3D12CreateDevice` with a preferred hardware adapter (falls back to WARP in debug builds). The device is the factory for creating all GPU resources. +- **`ID3D12CommandQueue`** — The queue for submitting command lists to the GPU for execution. +- **`ID3D12CommandAllocator`** (per back buffer) — Backing memory for command list recording. One per frame in flight to avoid GPU/CPU synchronization stalls. +- **`ID3D12GraphicsCommandList`** — Records rendering commands (draw calls, resource barriers, state changes) for submission to the command queue. +- **`IDXGISwapChain3`** — Created via `IDXGIFactory2::CreateSwapChainForHwnd`. Uses `DXGI_SWAP_EFFECT_FLIP_DISCARD` for modern flip-model presentation. +- **`ID3D12Resource`** (render targets) — The swap chain's back buffer resources. +- **`ID3D12DescriptorHeap`** (RTV) — Render target view descriptor heap for the swap chain back buffers. +- **`ID3D12Resource`** (depth stencil) — Created with `D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL` for depth testing. +- **`ID3D12DescriptorHeap`** (DSV) — Depth stencil view descriptor heap. +- **`ID3D12Fence`** — Used for CPU/GPU synchronization. Ensures the CPU does not overwrite command allocators or resources still in use by the GPU. +- **Debug layer** — In debug builds, enables `D3D12GetDebugInterface` and configures `ID3D12InfoQueue` to break on errors/corruption. + +> Unlike Direct3D 11, the application is responsible for all synchronization between CPU and GPU. The fence mechanism ensures safe reuse of per-frame resources. + +> Since we are going to ultimately be rendering a 3D scene in the tutorial, we are using the default values for the DeviceResources ctor. If we were only rendering 2D, we would pass ``DXGI_FORMAT_UNKNOWN`` for the *depthBufferFormat* parameter. + +### Game Loop + +The template's game loop follows a fixed pattern: + +1. `Game::Tick()` → calls `Update` (game logic with a step timer) then `Render` +2. `Render` → calls `DeviceResources::Prepare` (resets command allocator and command list, transitions back buffer to render target), performs `Clear` (sets render target and depth stencil views, clears them), draws, calls `DeviceResources::Present` +3. `Present` → transitions back buffer to present state, closes and executes command list, calls `IDXGISwapChain1::Present1` (with tearing flag if supported), advances fence value +4. Device lost handling — if `Present` returns `DXGI_ERROR_DEVICE_REMOVED`, calls `HandleDeviceLost` which recreates all resources and notifies the `Game` via `IDeviceNotify` + +### Key Differences from Direct3D 11 + +| Aspect | Direct3D 11 | Direct3D 12 | +| --- | --- | --- | +| Command submission | Immediate context | Command lists + command queue | +| Resource state | Driver-managed | Application-managed (resource barriers) | +| Descriptor binding | Bind slots | Descriptor heaps + root signatures | +| Pipeline state | Individual state objects | Monolithic pipeline state objects (PSOs) | +| Synchronization | Driver-managed | Application-managed (fences) | +| Memory management | Driver-managed | Application-managed | diff --git a/skills/directxtk12-tutorial/reference/step2.md b/skills/directxtk12-tutorial/reference/step2.md new file mode 100644 index 00000000..f0061c5e --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step2.md @@ -0,0 +1,128 @@ +# Step 2: Building the Project + +**Ask the user:** Would you like to build the project now? + +Detect the local system architecture to determine the appropriate platform target: + +```powershell +$arch = $env:PROCESSOR_ARCHITECTURE # AMD64 or ARM64 +``` + +## MSBuild + +For x64 systems: + +```powershell +msbuild .vcxproj /p:Configuration=Debug /p:Platform=x64 +``` + +For ARM64 systems: + +```powershell +msbuild .vcxproj /p:Configuration=Debug /p:Platform=ARM64 +``` + +> The first build will take longer as vcpkg downloads and builds the dependencies. + +## CMake + +For x64 systems: + +```powershell +cmake --preset=x64-Debug +cmake --build out\build\x64-Debug +``` + +For ARM64 systems: + +```powershell +cmake --preset=arm64-Debug +cmake --build out\build\arm64-Debug +``` + +> The first configure will take longer as vcpkg downloads and builds the dependencies. + +## Verifying the Build + +Once the build succeeds, the user should have a working executable that displays a cornflower blue window. Confirm the build completed without errors before proceeding to the next tutorial step. + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +The project template used in this tutorial uses VCPKG manifest mode to handle dependency management. The `vcpkg.json` file defines the libraries needed by the application, and the `vcpkg-configuration.json` provides a commit id for the vcpkg registry on [GitHub](https://github.com/microsoft/vcpkg) which controls the initial version of the dependencies. + +For this tutorial, we are relying on the default vcpkg integration offered in Visual Studio 2022 or later via `Microsoft.VisualStudio.Component.Vcpkg`. + +### MSBuild integration + +The vcpkg integration is handled directly in the `.vcxproj` project file: + +```xml + + true + +``` + +```xml + + x64-windows + +``` + +```xml + + + + $(VCInstallDir)vcpkg\scripts\buildsystems\msbuild\vcpkg-general.xml + +``` + +```xml + + x64-windows-static-md + + + arm64-windows-static-md + + + x64-windows-static-md + + + arm64-windows-static-md + +``` + +```xml + + +``` + +```xml + + + This project requires the VCPKG integration support in Visual Studio. Add the Microsoft.VisualStudio.Component.Vcpkg component to your install. + + + +``` + +> In more complex MSBuild solutions with multiple projects, the vcpkg integration is typically handled in a `Directory.Build.props` and `Directory.Build.targets` file. + +### CMake integration + +The `CMakePresets.json` sets `CMAKE_TOOLCHAIN_FILE` to vcpkg's toolchain discovered via the `VCPKG_ROOT` environment variable, which hooks into `find_package()` to locate installed packages. + +### Triplets + +The vcpkg **triplet** describes the architecture, configuration, and other properties of the build environment. + +| Triplet | Description | +| --------- | ------------- | +| `x64-windows` | x64 architecture, Windows, dynamic linking for Multithreaded DLL CRT | +| `arm64-windows` | ARM64 architecture, Windows, dynamic linking for Multithreaded DLL CRT | +| `x64-windows-static-md` | x64 architecture, Windows, static linking for Multi-threaded CRT | +| `arm64-windows-static-md` | ARM64 architecture, Windows, static linking for Multi-threaded CRT | + +There are two triplets active in a given build: the **host triplet** and the **target triplet**. The host triplet describes the machine on which the build is running, while the target triplet describes the machine for which the code is being built. diff --git a/skills/directxtk12-tutorial/reference/step3.md b/skills/directxtk12-tutorial/reference/step3.md new file mode 100644 index 00000000..5c2e0bf2 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step3.md @@ -0,0 +1,178 @@ +# Step 3: Adding DirectX Tool Kit + +Now add DirectX Tool Kit for DirectX 12 to the project via vcpkg. Edit the `vcpkg.json` manifest in the project root to add the `directxtk12` port with GameInput support. + +Add the following entry to the `"dependencies"` array in `vcpkg.json`: + +```json +{ + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput" + ] +} +``` + +For example, the full `vcpkg.json` should look something like: + +```json +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + { + "name": "directx-dxc", + "host": true + }, + "directx-dxc", + "directx-headers", + "directx12-agility", + "directxmath", + { + "name": "directxtk12", + "default-features": false, + "features": [ + "gameinput" + ] + } + ] +} +``` + +## CMake Projects + +For CMake projects, also add the following to `CMakeLists.txt`: + +```cmake +find_package(directxtk12 CONFIG REQUIRED) +find_package(gameinput CONFIG REQUIRED) +target_link_libraries(${PROJECT_NAME} PRIVATE Microsoft::DirectXTK12) +``` + +## Build and Verify + +Build the project to verify everything works. Use the same commands from [Step 2](step2.md). + +### MSBuild + +For x64 systems: + +```powershell +msbuild .vcxproj /p:Configuration=Debug /p:Platform=x64 +``` + +For ARM64 systems: + +```powershell +msbuild .vcxproj /p:Configuration=Debug /p:Platform=ARM64 +``` + +### CMake + +For x64 systems: + +```powershell +cmake --preset=x64-Debug +cmake --build out\build\x64-Debug +``` + +For ARM64 systems: + +```powershell +cmake --preset=arm64-Debug +cmake --build out\build\arm64-Debug +``` + +> The first rebuild will take longer as vcpkg fetches and builds DirectXTK12 and its dependencies (including GameInput). + +## Verifying the Integration + +Once the build succeeds, verify that the DirectXTK12 headers are available by adding a test include to `pch.h`: + +```cpp +#include +``` + +> **Important:** Use `` include style (not `"SpriteBatch.h"`) for proper MSBuild+vcpkg integration. + +If the build still succeeds, DirectXTK12 is properly integrated. + +## Adding the Headers and GraphicsMemory + +General advice for C++ projects is that you should only add the headers you actually use, but to simplify the tutorial we will go ahead and add the common ones to `pch.h`: + +```cpp +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +``` + +Next, add C++ namespace using statements to `Game.cpp` to make it easier to use the types: + +```cpp +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; +``` + +### Setting Up GraphicsMemory + +In DirectX 12, the application must manage the lifetime of all video memory resources. The `GraphicsMemory` class is a helper for managing dynamic allocations (constant buffers, dynamic vertex/index buffers, upload heaps). It must be created once and have `Commit` called once per frame. + +In **Game.h**, add the following private member variable: + +```cpp +std::unique_ptr m_graphicsMemory; +``` + +In **Game.cpp**, add to the TODO of **CreateDeviceDependentResources**: + +```cpp +m_graphicsMemory = std::make_unique(device); +``` + +In **Game.cpp**, in **Render** add a call to `GraphicsMemory::Commit` right after the present: + +```cpp +// Show the new frame. +m_deviceResources->Present(); +m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); +``` + +In **Game.cpp**, add to the TODO of **OnDeviceLost**: + +```cpp +m_graphicsMemory.reset(); +``` + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +- **Static linking** — The MSBuild template uses `-static-md` vcpkg triplets, so the DirectXTK12 library is statically linked. For CMake, the `DIRECTX_TOOLKIT_IMPORT` define is handled automatically by the CMake targets when using DLL triplets. + +- **Header location** — The DirectXTK12 headers are installed in the `include/directxtk12` directory of the `vcpkg_installed` folder for the given host/target triplet combination. The VCPKG+MSBuild integration only adds the root 'include' folder to the search paths for the build, so we have to specify the subdirectory explicitly. For CMake, the CMake targets automatically handle the specific header location, but with the use of the directxmath vcpkg port it also has the root folder in the search paths. + +- **GameInput** — A modern input API that provides a unified interface for gamepads, keyboards, and mice. It replaces the older XInput and raw input APIs. The vcpkg `gameinput` feature links the GameInput redistributable library. + +> **Important:** You may need to run GameInputRedist.msi which is installed into a tools folder in `vcpkg_installed` as part of the build process. + +- **vcpkg features** — The `"default-features": false` disables the default XInput backend so that only GameInput is used for input handling. This avoids linking both input systems. It also disables DirectX Tool Kit for Audio which we can add back later. + +- **GraphicsMemory** — In DirectX 12, the application is responsible for managing the lifetime of all video memory resources. The `GraphicsMemory` class is a helper for managing allocations and lifetimes for an 'upload heap'. This is used for constant buffers, dynamic vertex & index buffers, and as a source for copying data to 'dedicated video memory' on the GPU. Lifetime is managed by 'fences' which are injected once per frame, in combination with reference counts. The `Commit` method must be called once-per-frame to ensure proper tracking and cleanup. + +- **Shader Model 6** — DirectX Tool Kit for DirectX 12 requires Shader Model 6 support. The template includes a `CheckFeatureSupport` call to validate this at startup. diff --git a/skills/directxtk12-tutorial/reference/step4.md b/skills/directxtk12-tutorial/reference/step4.md new file mode 100644 index 00000000..1eca7aa4 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step4.md @@ -0,0 +1,214 @@ +# Step 4: Sprites and Textures + +This step adds 2D sprite rendering using `SpriteBatch` and loads a texture with `WICTextureLoader`. See the wiki page: [Sprites and textures](https://github.com/microsoft/DirectXTK12/wiki/Sprites-and-textures). + +## Setup + +Copy the `cat.png` file from this skill's `assets/` folder into the project's working directory (next to the executable, or in the project root for CMake builds): + +```powershell +Copy-Item "\assets\cat.png" -Destination "" +``` + +## Background + +In Direct3D 12, rendering a sprite requires significantly more explicit setup than in Direct3D 11: + +- A **committed resource** (the texture) containing the bitmap pixel data +- A **shader resource view descriptor** in a **descriptor heap** describing the texture +- A **pipeline state object** encapsulating all rendering state, shaders, and vertex layout +- A **root signature** defining how the GPU accesses resources +- A **ResourceUploadBatch** to manage the texture upload to GPU memory + +DirectX Tool Kit's `SpriteBatch` handles the pipeline state, root signature, vertex buffer, and draw calls. You just need to manage the texture resource, descriptor heap, and upload. + +## Code Changes + +### pch.h + +Ensure the following includes are in `pch.h` (they should already be there from Step 3): + +```cpp +#include +#include +#include +#include +#include +#include +#include +#include +#include +``` + +### Game.h + +Add the following private member variables to the `Game` class: + +```cpp +std::unique_ptr m_resourceDescriptors; +std::unique_ptr m_spriteBatch; +Microsoft::WRL::ComPtr m_texture; +DirectX::SimpleMath::Vector2 m_screenPos; +DirectX::SimpleMath::Vector2 m_origin; + +enum Descriptors +{ + Cat, + Count +}; +``` + +### Game.cpp — CreateDeviceDependentResources + +In `CreateDeviceDependentResources`, after creating `m_graphicsMemory`, create the descriptor heap, load the texture, create the SpriteBatch, and compute the sprite origin: + +```cpp +m_resourceDescriptors = std::make_unique(device, + Descriptors::Count); + +ResourceUploadBatch resourceUpload(device); + +resourceUpload.Begin(); + +DX::ThrowIfFailed( + CreateWICTextureFromFile(device, resourceUpload, L"cat.png", + m_texture.ReleaseAndGetAddressOf())); + +CreateShaderResourceView(device, m_texture.Get(), + m_resourceDescriptors->GetCpuHandle(Descriptors::Cat)); + +RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), + m_deviceResources->GetDepthBufferFormat()); + +SpriteBatchPipelineStateDescription pd(rtState, + &CommonStates::NonPremultiplied); +m_spriteBatch = std::make_unique(device, resourceUpload, pd); + +auto uploadResourcesFinished = resourceUpload.End( + m_deviceResources->GetCommandQueue()); + +uploadResourcesFinished.wait(); + +XMUINT2 catSize = GetTextureSize(m_texture.Get()); + +m_origin.x = float(catSize.x / 2); +m_origin.y = float(catSize.y / 2); +``` + +### Game.cpp — CreateWindowSizeDependentResources + +In `CreateWindowSizeDependentResources`, set up the viewport and compute the screen center position: + +```cpp +auto viewport = m_deviceResources->GetScreenViewport(); +m_spriteBatch->SetViewport(viewport); + +auto size = m_deviceResources->GetOutputSize(); +m_screenPos.x = float(size.right) / 2.f; +m_screenPos.y = float(size.bottom) / 2.f; +``` + +### Game.cpp — Render + +In the `Render` method, after clearing the render target and before `Present`, draw the sprite: + +```cpp +ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; +commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); + +m_spriteBatch->Begin(commandList); + +m_spriteBatch->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::Cat), + GetTextureSize(m_texture.Get()), + m_screenPos, nullptr, Colors::White, 0.f, m_origin); + +m_spriteBatch->End(); +``` + +### Game.cpp — OnDeviceLost + +In `OnDeviceLost`, release the resources: + +```cpp +m_spriteBatch.reset(); +m_texture.Reset(); +m_resourceDescriptors.reset(); +``` + +## Build and Verify + +Build the project using the commands from [Step 2](step2.md). To run the application, make sure the working directory is set to the project folder (where `cat.png` is located): + +```powershell +cd +``` + +For MSBuild, the executable will be in a subdirectory like `x64\Debug\.exe`. For CMake, it will be in `out\build\x64-Debug\.exe` (or the ARM64 equivalent). + +When you run the application, you should see the cat image rendered in the center of the window on top of the cornflower blue background. + +## Further Reading + +For more things you can do with sprites at this point: + +- [Sprites and textures](https://github.com/microsoft/DirectXTK12/wiki/Sprites-and-textures) + - Using DDS files for textures + - Using pre-multiplied alpha + - Rotating a sprite + - Scaling a sprite + - Tinting a sprite + - Tiling a sprite + - Stretching a sprite + - Drawing a background image +- [More tricks with sprites](https://github.com/microsoft/DirectXTK/wiki/More-tricks-with-sprites) + - Animating sprites + - Creating a scrolling background + - More to explore + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +### Key Differences from Direct3D 11 + +In Direct3D 11, `SpriteBatch` could be created with just a device context and would manage all its own state. In Direct3D 12: + +- You must create a **descriptor heap** and manage texture descriptors yourself +- You must create a **ResourceUploadBatch** to upload textures to GPU memory +- You must provide a **RenderTargetState** and create a pipeline state description when constructing `SpriteBatch` +- You must call `SetDescriptorHeaps` on the command list before drawing +- `SpriteBatch::Begin` takes a command list parameter instead of optional state overrides + +### SpriteBatch + +`SpriteBatch` is a high-performance batched 2D renderer. In Direct3D 12, it manages: + +- **Pipeline state object (PSO)** — Contains the compiled vertex and pixel shaders, input layout, blend state, depth/stencil state, and rasterizer state. Created at construction time from the `SpriteBatchPipelineStateDescription`. +- **Root signature** — Defines how shader parameters are bound. SpriteBatch uses a built-in root signature with a descriptor table for the texture SRV and a sampler. +- **Dynamic vertex buffer** (via `GraphicsMemory`) — Holds batched sprite quads. Uses sub-allocation from the upload heap managed by `GraphicsMemory`. +- **Index buffer** — Pre-generated indices for drawing quads as triangle lists. +- **Constant buffer** (via `GraphicsMemory`) — Contains the orthographic projection matrix for screen-space rendering. + +When you call `Begin(commandList)`/`End()`, SpriteBatch sets the pipeline state, root signature, and descriptor table bindings on the command list, then issues `DrawIndexedInstanced` calls, batching sprites that share the same texture into a single draw call. + +### ResourceUploadBatch + +`ResourceUploadBatch` manages the process of uploading texture data from CPU memory to GPU-accessible memory: + +1. `Begin()` — Starts recording upload commands. +2. Texture creation functions place data in an intermediate upload heap and record copy commands. +3. `End(commandQueue)` — Submits the copy commands to the GPU and returns a `std::future` for synchronization. +4. `.wait()` — Blocks until the GPU has completed all uploads. + +### DescriptorHeap + +`DescriptorHeap` is a simple wrapper around `ID3D12DescriptorHeap` that provides easy access to CPU and GPU descriptor handles by index. In Direct3D 12, textures are not bound directly — instead, a shader resource view (SRV) descriptor in a heap describes the texture, and the heap is set on the command list. + +### WICTextureLoader + +`CreateWICTextureFromFile` in DirectX 12 works differently from DirectX 11: + +- Creates an **`ID3D12Resource`** (committed resource) in the default heap as the final texture destination. +- Creates a temporary upload buffer in the upload heap. +- Records a copy command in the `ResourceUploadBatch` to transfer data from the upload heap to the default heap. +- The **shader resource view** must be created separately using `CreateShaderResourceView` (unlike DirectX 11 which created it automatically). diff --git a/skills/directxtk12-tutorial/reference/step5.md b/skills/directxtk12-tutorial/reference/step5.md new file mode 100644 index 00000000..7290577e --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step5.md @@ -0,0 +1,122 @@ +# Step 5: Drawing Text + +This step adds text rendering using `SpriteFont` and `SpriteBatch`. See the wiki page: [Drawing text](https://github.com/microsoft/DirectXTK12/wiki/Drawing-text). + +## Setup + +Copy the `courier.spritefont` file from this skill's `assets/` folder into the project's working directory: + +```powershell +Copy-Item "\assets\courier.spritefont" -Destination "" +``` + +> For details on how the sprite font is created, see the [MakeSpriteFont](https://github.com/microsoft/DirectXTK/wiki/MakeSpriteFont) wiki page. + +## Code Changes + +### pch.h + +Add the following include to `pch.h` (after the existing DirectXTK12 includes): + +```cpp +#include +``` + +### Game.h + +Add the following private member variable to the `Game` class: + +```cpp +std::unique_ptr m_font; +``` + +Also update the `Descriptors` enum to add a slot for the font texture: + +```cpp +enum Descriptors +{ + Cat, + MyFont, + Count +}; +``` + +### Game.cpp — CreateDeviceDependentResources + +In `CreateDeviceDependentResources`, load the sprite font inside the `ResourceUploadBatch` Begin/End block (after `resourceUpload.Begin()` and before `resourceUpload.End()`): + +```cpp +m_font = std::make_unique(device, resourceUpload, + L"courier.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::MyFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::MyFont)); +``` + +### Game.cpp — Render + +In the `Render` method, inside the existing `SpriteBatch` Begin/End block (after the sprite draw), add text rendering: + +```cpp +ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; +commandList->SetDescriptorHeaps(static_cast(std::size(heaps)), heaps); + +m_spriteBatch->Begin(commandList); + +m_spriteBatch->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::Cat), + GetTextureSize(m_texture.Get()), + m_screenPos, nullptr, Colors::White, 0.f, m_origin); + +m_font->DrawString(m_spriteBatch.get(), L"Hello, World!", + XMFLOAT2(10.f, 10.f), Colors::Yellow); + +m_spriteBatch->End(); +``` + +### Game.cpp — OnDeviceLost + +In `OnDeviceLost`, release the font: + +```cpp +m_font.reset(); +``` + +## Build and Verify + +Build the project using the commands from [Step 2](step2.md). Run the application from the project folder (where `courier.spritefont` is located). + +You should see "Hello, World!" rendered in yellow text in the top-left corner of the window, with the cat sprite still centered. + +## Further Reading + +- [Drawing text](https://github.com/microsoft/DirectXTK12/wiki/Drawing-text) + - Creating a font + - Using std::wstring for text + - Using ASCII text + - Drop-shadow effect + - Outline effect + - More to explore + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +### SpriteFont + +`SpriteFont` is a text rendering class that works in conjunction with `SpriteBatch`. In Direct3D 12, it manages: + +- **Font atlas** — A single **`ID3D12Resource`** (committed resource in the default heap) containing all pre-rendered glyphs packed into a texture atlas. The shader resource view is stored in the descriptor heap at the handle provided during construction. +- **Glyph data** — A sorted array of `Glyph` structs (loaded from the `.spritefont` binary format) containing character code, source rectangle in the atlas, and advance/offset metrics. + +**Text rendering pipeline:** + +1. `DrawString` iterates the input text character by character via an internal `ForEachGlyph` helper. +2. For each character, it performs a binary search to find the corresponding `Glyph` (falling back to a default character if not found). +3. It computes the destination position using the glyph offset, advance width, and any rotation/scale/origin transforms. +4. It calls `SpriteBatch::Draw` for each glyph, passing the font atlas GPU descriptor handle and the glyph's source rectangle. +5. `SpriteBatch` batches all glyph quads together (since they share the same atlas texture) and renders them in a single `DrawIndexedInstanced` call. + +The `.spritefont` binary format is produced by the **MakeSpriteFont** tool, which rasterizes a TrueType/OpenType font at a specific size and packs the glyphs into an atlas. + +### Descriptor Heap Management + +Note that both the cat texture and the font texture share the same `DescriptorHeap`. In Direct3D 12, you can only have one CBV/SRV/UAV descriptor heap and one sampler descriptor heap active at a time (set via `SetDescriptorHeaps`). By putting all texture descriptors in a single heap, we avoid the overhead of switching heaps during rendering. diff --git a/skills/directxtk12-tutorial/reference/step6.md b/skills/directxtk12-tutorial/reference/step6.md new file mode 100644 index 00000000..afc359a3 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step6.md @@ -0,0 +1,190 @@ +# Step 6: Simple Rendering + +This step introduces rendering custom geometry using `BasicEffect`, `PrimitiveBatch`, and `VertexPositionColor`. We draw a triangle with per-vertex colors (red, green, blue) that blend smoothly across the surface. See the wiki page: [Simple rendering](https://github.com/microsoft/DirectXTK12/wiki/Simple-rendering). + +## Background + +To draw geometry with Direct3D 12, you need: + +- A **vertex buffer** containing the vertices to draw +- A **root signature** which defines how the CPU and GPU shader programs share data +- A **pipeline state object** which defines all state, the vertex input layout, and the compiled shader programs +- A **primitive topology** setting that indicates how to interpret the individual vertices (as a point, a line, a triangle, etc.) + +DirectX Tool Kit simplifies this: + +| Requirement | DirectXTK12 Class | +| ------------- | ---------------- | +| Vertex buffer + topology | `PrimitiveBatch` | +| Root signature + PSO + shaders | `BasicEffect` + `EffectPipelineStateDescription` | +| State descriptions | `CommonStates` | +| Vertex format | `VertexPositionColor` | +| Render target format | `RenderTargetState` | + +## Code Changes + +### Game.cpp — Render (comment out sprite drawing keeping the text) + +First, comment out or remove the sprite drawing code from Step 4 in the `Render` method, since the triangle will cover the sprite: + +```cpp +// m_spriteBatch->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::Cat), +// GetTextureSize(m_texture.Get()), +// m_screenPos, nullptr, Colors::White, 0.f, m_origin); +``` + +### pch.h + +Ensure the following includes are in `pch.h`: + +```cpp +#include +#include +#include +#include +#include +#include +#include +``` + +### Game.h + +Add the following private member variables to the `Game` class: + +```cpp +using VertexType = DirectX::VertexPositionColor; + +std::unique_ptr m_effect; +std::unique_ptr> m_batch; +``` + +### Game.cpp — CreateDeviceDependentResources + +In `CreateDeviceDependentResources`, create the PrimitiveBatch, define the pipeline state, and create the effect: + +```cpp +auto device = m_deviceResources->GetD3DDevice(); + +m_batch = std::make_unique>(device); + +RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), + m_deviceResources->GetDepthBufferFormat()); + +EffectPipelineStateDescription pd( + &VertexType::InputLayout, + CommonStates::Opaque, + CommonStates::DepthNone, + CommonStates::CullNone, + rtState); + +m_effect = std::make_unique(device, EffectFlags::VertexColor, pd); +``` + +### Game.cpp — CreateWindowSizeDependentResources + +In `CreateWindowSizeDependentResources`, set up a projection matrix so we can use pixel coordinates (matching the SpriteBatch coordinate system): + +```cpp +auto size = m_deviceResources->GetOutputSize(); + +Matrix proj = Matrix::CreateOrthographicOffCenter( + 0.f, float(size.right), float(size.bottom), 0.f, 0.f, 1.f); +m_effect->SetProjection(proj); +``` + +### Game.cpp — Render + +In the `Render` method, after clearing the render target and before `Present`, draw the triangle: + +```cpp +m_effect->Apply(commandList); + +m_batch->Begin(commandList); + +VertexPositionColor v1(Vector3(400.f, 150.f, 0.f), Colors::Red); +VertexPositionColor v2(Vector3(600.f, 450.f, 0.f), Colors::Green); +VertexPositionColor v3(Vector3(200.f, 450.f, 0.f), Colors::Blue); + +m_batch->DrawTriangle(v1, v2, v3); + +m_batch->End(); +``` + +### Game.cpp — OnDeviceLost + +In `OnDeviceLost`, release the resources: + +```cpp +m_effect.reset(); +m_batch.reset(); +``` + +## Build and Verify + +Build the project using the commands from [Step 2](step2.md). When you run the application, you should see a triangle with smoothly interpolated red, green, and blue colors — the classic "rainbow triangle" — rendered on the cornflower blue background. + +The per-vertex colors are interpolated by the GPU rasterizer across the triangle surface, producing a smooth gradient between the three corner colors. + +## Coordinate Systems + +The code above uses **pixel coordinates** (origin at top-left, y-axis pointing down) thanks to the orthographic projection matrix. The triangle vertices are specified in screen pixels, matching the coordinate system used by `SpriteBatch`. + +Without the projection matrix, `BasicEffect` uses **normalized device coordinates** (-1 to +1 in both axes, origin at center). You can use either approach depending on your needs. + +## More to explore + +- [Simple rendering](https://github.com/microsoft/DirectXTK12/wiki/Simple-rendering) + - Drawing with normalized coordinates + - State objects and backface culling + - Drawing with textures + - Drawing with lighting and normal maps +- [Line drawing and anti-aliasing](https://github.com/microsoft/DirectXTK12/wiki/Line-drawing-and-anti-aliasing) + - Drawing a grid + - Anti-aliasing + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +### Pipeline State Objects (PSOs) + +In Direct3D 12, all shader and rendering state must be specified up-front in a monolithic **Pipeline State Object**. This is a critical difference from Direct3D 11 where state could be changed independently at any time. + +`EffectPipelineStateDescription` packages together: +- **Input layout** — From `VertexType::InputLayout`, describing vertex element format and offsets +- **Blend state** — From `CommonStates::Opaque` (no alpha blending) +- **Depth/stencil state** — From `CommonStates::DepthNone` (no depth testing for 2D) +- **Rasterizer state** — From `CommonStates::CullNone` (draw both sides) +- **Render target state** — Format of the render target and depth buffer + +The `BasicEffect` constructor takes this description and creates the PSO internally, combining it with its built-in root signature and compiled shaders. + +> In Direct3D 12, if you want to use different states (e.g., different blend mode or render target format), you must create a new effect instance with a new PSO. You cannot change state after PSO creation. + +### BasicEffect + +`BasicEffect` in Direct3D 12 manages: + +- **Pipeline state object** — Contains the compiled vertex and pixel shader permutation, input layout, and all fixed-function state. +- **Root signature** — Defines the parameter layout for the shaders. Built-in to the effect. +- **Constant buffer** (via `GraphicsMemory`) — Contains the world/view/projection matrices and material colors. Allocated dynamically each frame from the upload heap. + +When `Apply(commandList)` is called, it sets the PSO, root signature, and constant buffer on the command list. Unlike Direct3D 11, there is no separate input layout or state to set — it's all in the PSO. + +### PrimitiveBatch + +`PrimitiveBatch` is a lightweight immediate-mode geometry renderer: + +- **Dynamic vertex buffer** (via `GraphicsMemory`) — Allocated from the upload heap each frame. No persistent GPU buffer is needed. +- **Dynamic index buffer** (via `GraphicsMemory`) — Used when drawing indexed primitives. +- **No shader management** — Unlike `SpriteBatch`, `PrimitiveBatch` does not set the PSO or root signature. You must call `IEffect::Apply` yourself. +- **Topology** — Each draw call specifies the primitive topology. `DrawTriangle` uses `D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST`, `DrawLine` uses `LINELIST`. + +### The Rendering Pipeline + +When you call the render code above, here's what happens at the Direct3D 12 level: + +1. `m_effect->Apply(commandList)` — Sets the pipeline state object (PSO), root signature, and uploads the constant buffer with the current projection matrix. +2. `m_batch->Begin(commandList)` — Stores the command list reference for subsequent draw calls. +3. `DrawTriangle` — Allocates space from `GraphicsMemory` for 3 vertices, copies them in, sets the vertex buffer view, primitive topology, and issues a `DrawInstanced(3, ...)` call. +4. `m_batch->End()` — Flushes any remaining batched geometry. diff --git a/skills/directxtk12-tutorial/reference/step7.md b/skills/directxtk12-tutorial/reference/step7.md new file mode 100644 index 00000000..02c748b9 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/step7.md @@ -0,0 +1,224 @@ +# Step 7: 3D Shapes + +This step introduces rendering 3D geometry using `GeometricPrimitive`. We create and render a spinning teapot with default lighting. See the wiki page: [3D shapes](https://github.com/microsoft/DirectXTK12/wiki/3D-shapes). + +## Background + +In the previous step, we used `PrimitiveBatch` to draw geometry with manually specified vertices. `GeometricPrimitive` takes a different approach — it procedurally generates common 3D shapes (sphere, cube, torus, teapot, etc.) and stores them in vertex and index buffers. + +Key differences from `PrimitiveBatch`: + +| | PrimitiveBatch | GeometricPrimitive | +| --- | --- | --- | +| Buffer type | Dynamic (from upload heap each frame) | Static (can be uploaded to default heap) | +| Index buffer | Optional | Always used | +| Shader setup | Manual (you create and apply effect) | Manual (you create and apply effect) | +| Use case | Immediate-mode debug/simple drawing | Efficient 3D shape rendering | + +> Unlike _DirectX Tool Kit for DirectX 11_, you must create your own effect to render with `GeometricPrimitive` in the DirectX 12 version. + +## Code Changes + +### Game.cpp — Render (comment out previous step) + +Comment out or remove the triangle rendering code from Step 6: + +```cpp +// m_effect->Apply(commandList); +// m_batch->Begin(commandList); +// ... +// m_batch->End(); +``` + +### pch.h + +Ensure the following includes are in `pch.h`: + +```cpp +#include +#include +#include +#include +#include +#include +``` + +### Game.h + +Add the following private member variables to the `Game` class: + +```cpp +DirectX::SimpleMath::Matrix m_world; +DirectX::SimpleMath::Matrix m_view; +DirectX::SimpleMath::Matrix m_proj; + +std::unique_ptr m_shape; +std::unique_ptr m_shapeEffect; +``` + +### Game.cpp — CreateDeviceDependentResources + +In `CreateDeviceDependentResources`, create the pipeline state, effect, and shape: + +```cpp +auto device = m_deviceResources->GetD3DDevice(); + +RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), + m_deviceResources->GetDepthBufferFormat()); + +EffectPipelineStateDescription pd( + &GeometricPrimitive::VertexType::InputLayout, + CommonStates::Opaque, + CommonStates::DepthDefault, + CommonStates::CullNone, + rtState); + +m_shapeEffect = std::make_unique(device, EffectFlags::Lighting, pd); +m_shapeEffect->EnableDefaultLighting(); + +m_shape = GeometricPrimitive::CreateTeapot(); + +m_world = Matrix::Identity; +``` + +### Game.cpp — CreateWindowSizeDependentResources + +In `CreateWindowSizeDependentResources`, set up a 3D camera with a perspective projection: + +```cpp +auto size = m_deviceResources->GetOutputSize(); + +m_view = Matrix::CreateLookAt( + Vector3(2.f, 2.f, 2.f), + Vector3::Zero, + Vector3::UnitY); + +m_proj = Matrix::CreatePerspectiveFieldOfView( + XM_PI / 4.f, + float(size.right) / float(size.bottom), + 0.1f, 10.f); + +m_shapeEffect->SetView(m_view); +m_shapeEffect->SetProjection(m_proj); +``` + +### Game.cpp — Update + +In `Update`, rotate the shape over time: + +```cpp +auto time = static_cast(timer.GetTotalSeconds()); + +m_world = Matrix::CreateRotationZ(cosf(time) * 2.f); +``` + +### Game.cpp — Render + +In the `Render` method, after clearing the render target and before `Present`, draw the shape: + +```cpp +m_shapeEffect->SetWorld(m_world); + +m_shapeEffect->Apply(commandList); + +m_shape->Draw(commandList); +``` + +### Game.cpp — OnDeviceLost + +In `OnDeviceLost`, release the shape and effect: + +```cpp +m_shape.reset(); +m_shapeEffect.reset(); +``` + +## Build and Verify + +Build the project using the commands from [Step 2](step2.md). When you run the application, you should see a white, lit teapot rotating on the cornflower blue background. + +The teapot is rendered with default lighting (three directional lights) and backface culling disabled, giving it a solid 3D appearance. + +## Optimizing with Static Buffers + +By default, `GeometricPrimitive` creates its vertex and index buffers using `GraphicsMemory` (upload heap memory). You can upload them to dedicated video memory for faster render performance by using `ResourceUploadBatch`: + +```cpp +m_shape = GeometricPrimitive::CreateTeapot(); + +ResourceUploadBatch resourceUpload(device); + +resourceUpload.Begin(); + +m_shape->LoadStaticBuffers(device, resourceUpload); + +auto uploadResourcesFinished = resourceUpload.End( + m_deviceResources->GetCommandQueue()); + +uploadResourcesFinished.wait(); +``` + +## Available Shapes + +`GeometricPrimitive` can create many shapes. Replace `CreateTeapot` with any of these: + +| Factory Method | Shape | +| --- | --- | +| `CreateSphere` | UV sphere | +| `CreateGeoSphere` | Geodesic sphere | +| `CreateCube` | Unit cube | +| `CreateBox` | Axis-aligned box with custom dimensions | +| `CreateCylinder` | Cylinder | +| `CreateCone` | Cone | +| `CreateTorus` | Torus (donut) | +| `CreateTetrahedron` | Tetrahedron (4 faces) | +| `CreateOctahedron` | Octahedron (8 faces) | +| `CreateDodecahedron` | Dodecahedron (12 faces) | +| `CreateIcosahedron` | Icosahedron (20 faces) | +| `CreateTeapot` | Utah teapot | + +## Next Steps + +See [Next Steps](nextsteps.md) for where to go from here. + +## Further Reading + +- [3D shapes](https://github.com/microsoft/DirectXTK12/wiki/3D-shapes) + - Adding textures to shapes + - Using custom lighting and effects + - Custom vertex formats + - Custom geometry +- [Rendering a model](https://github.com/microsoft/DirectXTK12/wiki/Rendering-a-model) + +## Technical Notes + +**Ask the user:** Would you like to see the Technical Notes for this step, or skip to the next step? + +### GeometricPrimitive + +`GeometricPrimitive` procedurally generates indexed triangle meshes: + +- **Vertex data** — `VertexPositionNormalTexture` format (position, normal, and texture coordinates). +- **Index data** — `uint16_t` indices for indexed rendering, reducing vertex count by sharing vertices between adjacent triangles. +- **Default storage** — Uses `GraphicsMemory` (upload heap) for immediate rendering. +- **Static buffers** — `LoadStaticBuffers` creates `ID3D12Resource` committed resources in the default heap (fast GPU memory) and uses `ResourceUploadBatch` to copy data there. + +Unlike the Direct3D 11 version, you must provide your own effect. The DX11 version had a convenience `Draw(world, view, proj)` overload that managed an internal `BasicEffect`, but the DX12 version requires explicit effect and PSO management. + +### The 3D Camera + +This step introduces a proper 3D camera setup: + +- **View matrix** (`CreateLookAt`) — Defines where the camera is (eye position), what it's looking at (focus point), and which direction is "up". This transforms world-space coordinates into camera-space (view-space). +- **Projection matrix** (`CreatePerspectiveFieldOfView`) — Defines the camera's field of view, aspect ratio, and near/far clipping planes. This transforms view-space into clip-space, applying perspective foreshortening so distant objects appear smaller. + +Together, these matrices transform the shape's local vertex positions through: **World → View → Projection → Clip Space** → (GPU viewport transform) → **Screen pixels**. + +### Upload Heap vs. Default Heap + +- **Upload heap** (`GraphicsMemory`) — CPU-writable memory accessible by the GPU. Good for data that changes per-frame (constant buffers, dynamic geometry). This is what `PrimitiveBatch` and default `GeometricPrimitive` use. +- **Default heap** (via `LoadStaticBuffers`) — GPU-only memory. Data must be copied there via a command list. Much faster for the GPU to read, but requires explicit upload management. Used for static geometry that doesn't change. + +### The Utah Teapot + +The [Utah teapot](https://en.wikipedia.org/wiki/Utah_teapot) is a classic test model in computer graphics, originally created by Martin Newell in 1975. DirectX Tool Kit generates it from Bézier patch data, tessellated to the specified level (default: 8). diff --git a/skills/directxtk12-tutorial/reference/tutorial-steps.md b/skills/directxtk12-tutorial/reference/tutorial-steps.md new file mode 100644 index 00000000..65448921 --- /dev/null +++ b/skills/directxtk12-tutorial/reference/tutorial-steps.md @@ -0,0 +1,18 @@ +# Tutorial Steps + +This document outlines the sequence of lessons in the DirectX Tool Kit for DirectX 12 Getting Started tutorial. + +Each lesson is documented on the [DirectXTK12 wiki](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started). + +## Lesson Sequence + +| # | Lesson | Wiki Page | Summary | +| --- | -------- | ----------- | --------- | +| 0 | Prerequisites | [Getting Started](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) | Verify required tools: Visual Studio, Windows SDK, vcpkg, Git, and D3D12-capable GPU | +| 1 | Project Setup | [Getting Started](https://github.com/microsoft/DirectXTK12/wiki/Getting-Started) | Create a new Direct3D 12 project using the d3d12game_vcpkg template | +| 2 | Building the project | | Build the project and resolve any dependencies | +| 3 | Adding DirectXTK12 | [Adding the DirectX Tool Kit](https://github.com/microsoft/DirectXTK12/wiki/Adding-the-DirectX-Tool-Kit) | Integrate DirectXTK12 into the project via vcpkg and set up GraphicsMemory | +| 4 | Sprites and Textures | [Sprites and textures](https://github.com/microsoft/DirectXTK12/wiki/Sprites-and-textures) | Render 2D sprites using SpriteBatch with descriptor heaps | +| 5 | Drawing Text | [Drawing text](https://github.com/microsoft/DirectXTK12/wiki/Drawing-text) | Render text using SpriteFont | +| 6 | Simple Rendering | [Simple rendering](https://github.com/microsoft/DirectXTK12/wiki/Simple-rendering) | Draw simple triangle primitives with pipeline state objects | +| 7 | 3D Shapes | [3D shapes](https://github.com/microsoft/DirectXTK12/wiki/3D-shapes) | Use GeometricPrimitive for standard 3D shapes | From 8fc095bb2a970c46029bac4b66daede5c6f47f97 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Fri, 5 Jun 2026 10:08:06 -0700 Subject: [PATCH 11/11] Pick markdown lint --- skills/directxtk12-tutorial/reference/step1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/directxtk12-tutorial/reference/step1.md b/skills/directxtk12-tutorial/reference/step1.md index d86eb065..5c98c6d8 100644 --- a/skills/directxtk12-tutorial/reference/step1.md +++ b/skills/directxtk12-tutorial/reference/step1.md @@ -118,7 +118,7 @@ The `DeviceResources` class encapsulates all Direct3D 12 device and swap chain m > Unlike Direct3D 11, the application is responsible for all synchronization between CPU and GPU. The fence mechanism ensures safe reuse of per-frame resources. -> Since we are going to ultimately be rendering a 3D scene in the tutorial, we are using the default values for the DeviceResources ctor. If we were only rendering 2D, we would pass ``DXGI_FORMAT_UNKNOWN`` for the *depthBufferFormat* parameter. +Since we are going to ultimately be rendering a 3D scene in the tutorial, we are using the default values for the DeviceResources ctor. If we were only rendering 2D, we would pass ``DXGI_FORMAT_UNKNOWN`` for the *depthBufferFormat* parameter. ### Game Loop