From 550385df796171e98b72b6ee385790f9579cf2e5 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 30 Jun 2016 19:44:17 -0700 Subject: [PATCH] June 2016 --- Kits/ATGTK/ControllerFont.h | 215 + Kits/ATGTK/TextConsole.cpp | 4 +- Kits/DirectXTK/DirectXTK_Windows10.vcxproj | 6 +- .../DirectXTK_Windows10.vcxproj.filters | 133 +- Kits/DirectXTK/Inc/GamePad.h | 31 +- Kits/DirectXTK/Inc/Keyboard.h | 2 + Kits/DirectXTK/Inc/Mouse.h | 2 + Kits/DirectXTK/Inc/PrimitiveBatch.h | 14 +- Kits/DirectXTK/Inc/ScreenGrab.h | 4 +- Kits/DirectXTK/Inc/SimpleMath.h | 30 +- Kits/DirectXTK/Inc/SimpleMath.inl | 12 + Kits/DirectXTK/Inc/SpriteFont.h | 5 +- Kits/DirectXTK/Readme.txt | 23 +- Kits/DirectXTK/Src/DDSTextureLoader.cpp | 731 +--- Kits/DirectXTK/Src/DGSLEffectFactory.cpp | 24 + Kits/DirectXTK/Src/EffectFactory.cpp | 12 + Kits/DirectXTK/Src/GamePad.cpp | 32 + Kits/DirectXTK/Src/GeometricPrimitive.cpp | 1144 +---- Kits/DirectXTK/Src/Geometry.cpp | 1184 ++++++ Kits/DirectXTK/Src/Geometry.h | 32 + Kits/DirectXTK/Src/LoaderHelpers.h | 858 ++++ Kits/DirectXTK/Src/ModelLoadSDKMESH.cpp | 757 +--- Kits/DirectXTK/Src/ModelLoadVBO.cpp | 52 +- Kits/DirectXTK/Src/SDKMesh.h | 340 ++ Kits/DirectXTK/Src/ScreenGrab.cpp | 443 +- .../AlphaTestEffect_PSAlphaTestEqNe.inc | 62 +- .../AlphaTestEffect_PSAlphaTestEqNeNoFog.inc | 52 +- .../AlphaTestEffect_PSAlphaTestLtGt.inc | 58 +- .../AlphaTestEffect_PSAlphaTestLtGtNoFog.inc | 48 +- .../Compiled/AlphaTestEffect_VSAlphaTest.inc | 68 +- .../AlphaTestEffect_VSAlphaTestNoFog.inc | 58 +- .../AlphaTestEffect_VSAlphaTestVc.inc | 74 +- .../AlphaTestEffect_VSAlphaTestVcNoFog.inc | 60 +- .../Shaders/Compiled/BasicEffect_PSBasic.inc | 44 +- .../Compiled/BasicEffect_PSBasicNoFog.inc | 34 +- .../BasicEffect_PSBasicPixelLighting.inc | 138 +- .../BasicEffect_PSBasicPixelLightingTx.inc | 146 +- .../Compiled/BasicEffect_PSBasicTx.inc | 52 +- .../Compiled/BasicEffect_PSBasicTxNoFog.inc | 42 +- .../BasicEffect_PSBasicVertexLighting.inc | 46 +- ...BasicEffect_PSBasicVertexLightingNoFog.inc | 42 +- .../BasicEffect_PSBasicVertexLightingTx.inc | 54 +- ...sicEffect_PSBasicVertexLightingTxNoFog.inc | 50 +- .../Shaders/Compiled/BasicEffect_VSBasic.inc | 62 +- .../Compiled/BasicEffect_VSBasicNoFog.inc | 52 +- .../Compiled/BasicEffect_VSBasicOneLight.inc | 114 +- .../BasicEffect_VSBasicOneLightTx.inc | 120 +- .../BasicEffect_VSBasicOneLightTxVc.inc | 124 +- .../BasicEffect_VSBasicOneLightVc.inc | 120 +- .../BasicEffect_VSBasicPixelLighting.inc | 86 +- .../BasicEffect_VSBasicPixelLightingTx.inc | 90 +- .../BasicEffect_VSBasicPixelLightingTxVc.inc | 94 +- .../BasicEffect_VSBasicPixelLightingVc.inc | 90 +- .../Compiled/BasicEffect_VSBasicTx.inc | 68 +- .../Compiled/BasicEffect_VSBasicTxNoFog.inc | 58 +- .../Compiled/BasicEffect_VSBasicTxVc.inc | 74 +- .../Compiled/BasicEffect_VSBasicTxVcNoFog.inc | 60 +- .../Compiled/BasicEffect_VSBasicVc.inc | 68 +- .../Compiled/BasicEffect_VSBasicVcNoFog.inc | 56 +- .../BasicEffect_VSBasicVertexLighting.inc | 150 +- .../BasicEffect_VSBasicVertexLightingTx.inc | 156 +- .../BasicEffect_VSBasicVertexLightingTxVc.inc | 160 +- .../BasicEffect_VSBasicVertexLightingVc.inc | 156 +- .../Src/Shaders/Compiled/DGSLEffect_main.inc | 80 +- .../Compiled/DGSLEffect_main1Bones.inc | 114 +- .../Compiled/DGSLEffect_main1BonesVc.inc | 116 +- .../Compiled/DGSLEffect_main2Bones.inc | 120 +- .../Compiled/DGSLEffect_main2BonesVc.inc | 122 +- .../Compiled/DGSLEffect_main4Bones.inc | 132 +- .../Compiled/DGSLEffect_main4BonesVc.inc | 134 +- .../Shaders/Compiled/DGSLEffect_mainVc.inc | 82 +- .../Src/Shaders/Compiled/DGSLLambert_main.inc | 68 +- .../Shaders/Compiled/DGSLLambert_mainTk.inc | 76 +- .../Shaders/Compiled/DGSLLambert_mainTx.inc | 76 +- .../Shaders/Compiled/DGSLLambert_mainTxTk.inc | 84 +- .../Src/Shaders/Compiled/DGSLPhong_main.inc | 120 +- .../Src/Shaders/Compiled/DGSLPhong_mainTk.inc | 126 +- .../Src/Shaders/Compiled/DGSLPhong_mainTx.inc | 126 +- .../Shaders/Compiled/DGSLPhong_mainTxTk.inc | 132 +- .../Src/Shaders/Compiled/DGSLUnlit_main.inc | 34 +- .../Src/Shaders/Compiled/DGSLUnlit_mainTk.inc | 44 +- .../Src/Shaders/Compiled/DGSLUnlit_mainTx.inc | 42 +- .../Shaders/Compiled/DGSLUnlit_mainTxTk.inc | 52 +- .../DualTextureEffect_PSDualTexture.inc | 64 +- .../DualTextureEffect_PSDualTextureNoFog.inc | 54 +- .../DualTextureEffect_VSDualTexture.inc | 72 +- .../DualTextureEffect_VSDualTextureNoFog.inc | 62 +- .../DualTextureEffect_VSDualTextureVc.inc | 78 +- ...DualTextureEffect_VSDualTextureVcNoFog.inc | 64 +- .../EnvironmentMapEffect_PSEnvMap.inc | 62 +- .../EnvironmentMapEffect_PSEnvMapNoFog.inc | 54 +- .../EnvironmentMapEffect_PSEnvMapSpecular.inc | 66 +- ...ronmentMapEffect_PSEnvMapSpecularNoFog.inc | 58 +- .../EnvironmentMapEffect_VSEnvMap.inc | 122 +- .../EnvironmentMapEffect_VSEnvMapFresnel.inc | 132 +- .../EnvironmentMapEffect_VSEnvMapOneLight.inc | 114 +- ...nmentMapEffect_VSEnvMapOneLightFresnel.inc | 124 +- .../SkinnedEffect_PSSkinnedPixelLighting.inc | 146 +- .../SkinnedEffect_PSSkinnedVertexLighting.inc | 54 +- ...nedEffect_PSSkinnedVertexLightingNoFog.inc | 50 +- ...innedEffect_VSSkinnedOneLightFourBones.inc | 168 +- ...SkinnedEffect_VSSkinnedOneLightOneBone.inc | 150 +- ...kinnedEffect_VSSkinnedOneLightTwoBones.inc | 156 +- ...Effect_VSSkinnedPixelLightingFourBones.inc | 138 +- ...edEffect_VSSkinnedPixelLightingOneBone.inc | 120 +- ...dEffect_VSSkinnedPixelLightingTwoBones.inc | 126 +- ...ffect_VSSkinnedVertexLightingFourBones.inc | 204 +- ...dEffect_VSSkinnedVertexLightingOneBone.inc | 186 +- ...Effect_VSSkinnedVertexLightingTwoBones.inc | 192 +- .../SpriteEffect_SpritePixelShader.inc | 42 +- .../SpriteEffect_SpriteVertexShader.inc | 52 +- Kits/DirectXTK/Src/SharedResourcePool.h | 10 +- Kits/DirectXTK/Src/SimpleMath.cpp | 12 + Kits/DirectXTK/Src/SpriteFont.cpp | 63 +- Kits/DirectXTK/Src/WICTextureLoader.cpp | 34 +- Kits/DirectXTK/Src/dds.h | 10 +- Kits/DirectXTK/Src/pch.h | 3 + Kits/DirectXTK/Src/vbo.h | 38 + Kits/DirectXTK12/Audio/AudioEngine.cpp | 1724 ++++++++ .../Audio/DynamicSoundEffectInstance.cpp | 376 ++ Kits/DirectXTK12/Audio/SoundCommon.cpp | 787 ++++ Kits/DirectXTK12/Audio/SoundCommon.h | 369 ++ Kits/DirectXTK12/Audio/SoundEffect.cpp | 617 +++ .../DirectXTK12/Audio/SoundEffectInstance.cpp | 334 ++ Kits/DirectXTK12/Audio/WAVFileReader.cpp | 681 +++ Kits/DirectXTK12/Audio/WAVFileReader.h | 55 + Kits/DirectXTK12/Audio/WaveBank.cpp | 511 +++ Kits/DirectXTK12/Audio/WaveBankReader.cpp | 1376 ++++++ Kits/DirectXTK12/Audio/WaveBankReader.h | 80 + Kits/DirectXTK12/DirectXTK_Windows10.vcxproj | 454 ++ .../DirectXTK_Windows10.vcxproj.filters | 521 +++ Kits/DirectXTK12/Inc/Audio.h | 682 +++ Kits/DirectXTK12/Inc/CommonStates.h | 55 + Kits/DirectXTK12/Inc/DDSTextureLoader.h | 139 + Kits/DirectXTK12/Inc/DescriptorHeap.h | 126 + Kits/DirectXTK12/Inc/DirectXHelpers.h | 176 + Kits/DirectXTK12/Inc/Effects.h | 545 +++ Kits/DirectXTK12/Inc/GamePad.h | 260 ++ Kits/DirectXTK12/Inc/GeometricPrimitive.h | 75 + Kits/DirectXTK12/Inc/GraphicsMemory.h | 122 + Kits/DirectXTK12/Inc/Keyboard.h | 479 +++ Kits/DirectXTK12/Inc/Model.h | 287 ++ Kits/DirectXTK12/Inc/Mouse.h | 120 + Kits/DirectXTK12/Inc/PrimitiveBatch.h | 144 + Kits/DirectXTK12/Inc/RenderTargetState.h | 77 + Kits/DirectXTK12/Inc/ResourceUploadBatch.h | 73 + Kits/DirectXTK12/Inc/ScreenGrab.h | 52 + Kits/DirectXTK12/Inc/SimpleMath.h | 1020 +++++ Kits/DirectXTK12/Inc/SimpleMath.inl | 3706 +++++++++++++++++ Kits/DirectXTK12/Inc/SpriteBatch.h | 143 + Kits/DirectXTK12/Inc/SpriteFont.h | 81 + Kits/DirectXTK12/Inc/VertexTypes.h | 285 ++ Kits/DirectXTK12/Inc/WICTextureLoader.h | 78 + Kits/DirectXTK12/Readme.txt | 97 + Kits/DirectXTK12/Src/AlignedNew.h | 67 + Kits/DirectXTK12/Src/AlphaTestEffect.cpp | 443 ++ Kits/DirectXTK12/Src/BasicEffect.cpp | 601 +++ Kits/DirectXTK12/Src/Bezier.h | 169 + Kits/DirectXTK12/Src/BinaryReader.cpp | 90 + Kits/DirectXTK12/Src/BinaryReader.h | 75 + Kits/DirectXTK12/Src/CommonStates.cpp | 320 ++ Kits/DirectXTK12/Src/DDSTextureLoader.cpp | 827 ++++ Kits/DirectXTK12/Src/DemandCreate.h | 51 + Kits/DirectXTK12/Src/DescriptorHeap.cpp | 179 + Kits/DirectXTK12/Src/DirectXHelpers.cpp | 99 + Kits/DirectXTK12/Src/DualTextureEffect.cpp | 344 ++ Kits/DirectXTK12/Src/EffectCommon.cpp | 365 ++ Kits/DirectXTK12/Src/EffectCommon.h | 255 ++ Kits/DirectXTK12/Src/EffectFactory.cpp | 389 ++ Kits/DirectXTK12/Src/EffectTextureFactory.cpp | 282 ++ Kits/DirectXTK12/Src/EnvironmentMapEffect.cpp | 498 +++ Kits/DirectXTK12/Src/GamePad.cpp | 1239 ++++++ Kits/DirectXTK12/Src/GenericMultiBuffer.h | 71 + Kits/DirectXTK12/Src/GeometricPrimitive.cpp | 434 ++ Kits/DirectXTK12/Src/Geometry.cpp | 1184 ++++++ Kits/DirectXTK12/Src/Geometry.h | 32 + Kits/DirectXTK12/Src/GraphicsMemory.cpp | 365 ++ Kits/DirectXTK12/Src/Keyboard.cpp | 520 +++ Kits/DirectXTK12/Src/LinearAllocator.cpp | 498 +++ Kits/DirectXTK12/Src/LinearAllocator.h | 161 + Kits/DirectXTK12/Src/LoaderHelpers.h | 858 ++++ Kits/DirectXTK12/Src/Model.cpp | 279 ++ Kits/DirectXTK12/Src/ModelLoadSDKMESH.cpp | 576 +++ Kits/DirectXTK12/Src/ModelLoadVBO.cpp | 132 + Kits/DirectXTK12/Src/Mouse.cpp | 961 +++++ Kits/DirectXTK12/Src/PlatformHelpers.h | 152 + Kits/DirectXTK12/Src/PrimitiveBatch.cpp | 282 ++ Kits/DirectXTK12/Src/ResourceUploadBatch.cpp | 589 +++ Kits/DirectXTK12/Src/SDKMesh.h | 340 ++ Kits/DirectXTK12/Src/ScreenGrab.cpp | 713 ++++ .../Src/Shaders/AlphaTestEffect.fx | 140 + Kits/DirectXTK12/Src/Shaders/BasicEffect.fx | 471 +++ Kits/DirectXTK12/Src/Shaders/Common.fxh | 60 + .../Src/Shaders/CompileShaders.cmd | 166 + .../AlphaTestEffect_PSAlphaTestEqNe.inc | 182 + .../AlphaTestEffect_PSAlphaTestEqNeNoFog.inc | 159 + .../AlphaTestEffect_PSAlphaTestLtGt.inc | 173 + .../AlphaTestEffect_PSAlphaTestLtGtNoFog.inc | 150 + .../Compiled/AlphaTestEffect_VSAlphaTest.inc | 175 + .../AlphaTestEffect_VSAlphaTestNoFog.inc | 154 + .../AlphaTestEffect_VSAlphaTestVc.inc | 185 + .../AlphaTestEffect_VSAlphaTestVcNoFog.inc | 164 + .../Shaders/Compiled/BasicEffect_PSBasic.inc | 120 + .../Compiled/BasicEffect_PSBasicNoFog.inc | 90 + .../BasicEffect_PSBasicPixelLighting.inc | 392 ++ .../BasicEffect_PSBasicPixelLightingTx.inc | 420 ++ .../Compiled/BasicEffect_PSBasicTx.inc | 150 + .../Compiled/BasicEffect_PSBasicTxNoFog.inc | 118 + .../BasicEffect_PSBasicVertexLighting.inc | 127 + ...BasicEffect_PSBasicVertexLightingNoFog.inc | 105 + .../BasicEffect_PSBasicVertexLightingTx.inc | 157 + ...sicEffect_PSBasicVertexLightingTxNoFog.inc | 138 + .../Shaders/Compiled/BasicEffect_VSBasic.inc | 151 + .../Compiled/BasicEffect_VSBasicNoFog.inc | 131 + .../Compiled/BasicEffect_VSBasicOneLight.inc | 335 ++ .../BasicEffect_VSBasicOneLightTx.inc | 358 ++ .../BasicEffect_VSBasicOneLightTxVc.inc | 374 ++ .../BasicEffect_VSBasicOneLightVc.inc | 351 ++ .../BasicEffect_VSBasicPixelLighting.inc | 226 + .../BasicEffect_VSBasicPixelLightingTx.inc | 248 ++ .../BasicEffect_VSBasicPixelLightingTxVc.inc | 256 ++ .../BasicEffect_VSBasicPixelLightingVc.inc | 235 ++ .../Compiled/BasicEffect_VSBasicTx.inc | 175 + .../Compiled/BasicEffect_VSBasicTxNoFog.inc | 154 + .../Compiled/BasicEffect_VSBasicTxVc.inc | 185 + .../Compiled/BasicEffect_VSBasicTxVcNoFog.inc | 164 + .../Compiled/BasicEffect_VSBasicVc.inc | 162 + .../Compiled/BasicEffect_VSBasicVcNoFog.inc | 141 + .../BasicEffect_VSBasicVertexLighting.inc | 445 ++ .../BasicEffect_VSBasicVertexLightingTx.inc | 468 +++ .../BasicEffect_VSBasicVertexLightingTxVc.inc | 484 +++ .../BasicEffect_VSBasicVertexLightingVc.inc | 461 ++ .../DualTextureEffect_PSDualTexture.inc | 201 + .../DualTextureEffect_PSDualTextureNoFog.inc | 170 + .../DualTextureEffect_VSDualTexture.inc | 211 + .../DualTextureEffect_VSDualTextureNoFog.inc | 190 + .../DualTextureEffect_VSDualTextureVc.inc | 221 + ...DualTextureEffect_VSDualTextureVcNoFog.inc | 200 + .../EnvironmentMapEffect_PSEnvMap.inc | 203 + .../EnvironmentMapEffect_PSEnvMapNoFog.inc | 184 + .../EnvironmentMapEffect_PSEnvMapSpecular.inc | 216 + ...ronmentMapEffect_PSEnvMapSpecularNoFog.inc | 201 + .../EnvironmentMapEffect_VSEnvMap.inc | 377 ++ .../EnvironmentMapEffect_VSEnvMapFresnel.inc | 411 ++ .../EnvironmentMapEffect_VSEnvMapOneLight.inc | 343 ++ ...nmentMapEffect_VSEnvMapOneLightFresnel.inc | 377 ++ .../Shaders/Compiled/GenerateMips_main.inc | 145 + .../SkinnedEffect_PSSkinnedPixelLighting.inc | 420 ++ .../SkinnedEffect_PSSkinnedVertexLighting.inc | 157 + ...nedEffect_PSSkinnedVertexLightingNoFog.inc | 138 + ...innedEffect_VSSkinnedOneLightFourBones.inc | 529 +++ ...SkinnedEffect_VSSkinnedOneLightOneBone.inc | 446 ++ ...kinnedEffect_VSSkinnedOneLightTwoBones.inc | 475 +++ ...Effect_VSSkinnedPixelLightingFourBones.inc | 419 ++ ...edEffect_VSSkinnedPixelLightingOneBone.inc | 336 ++ ...dEffect_VSSkinnedPixelLightingTwoBones.inc | 365 ++ ...ffect_VSSkinnedVertexLightingFourBones.inc | 639 +++ ...dEffect_VSSkinnedVertexLightingOneBone.inc | 556 +++ ...Effect_VSSkinnedVertexLightingTwoBones.inc | 585 +++ .../SpriteEffect_SpritePixelShader.inc | 118 + .../SpriteEffect_SpriteVertexShader.inc | 169 + .../Src/Shaders/DualTextureEffect.fx | 126 + .../Src/Shaders/EnvironmentMapEffect.fx | 175 + .../DirectXTK12/Src/Shaders/GenerateMips.hlsl | 37 + Kits/DirectXTK12/Src/Shaders/Lighting.fxh | 97 + Kits/DirectXTK12/Src/Shaders/RootSig.fxh | 44 + Kits/DirectXTK12/Src/Shaders/SkinnedEffect.fx | 259 ++ Kits/DirectXTK12/Src/Shaders/SpriteEffect.fx | 36 + Kits/DirectXTK12/Src/Shaders/Structures.fxh | 229 + Kits/DirectXTK12/Src/SharedResourcePool.h | 105 + Kits/DirectXTK12/Src/SimpleMath.cpp | 192 + Kits/DirectXTK12/Src/SkinnedEffect.cpp | 550 +++ Kits/DirectXTK12/Src/SpriteBatch.cpp | 1078 +++++ Kits/DirectXTK12/Src/SpriteFont.cpp | 532 +++ Kits/DirectXTK12/Src/TeapotData.inc | 185 + Kits/DirectXTK12/Src/VertexTypes.cpp | 166 + Kits/DirectXTK12/Src/WICTextureLoader.cpp | 693 +++ Kits/DirectXTK12/Src/d3dx12.h | 1534 +++++++ Kits/DirectXTK12/Src/dds.h | 228 + Kits/DirectXTK12/Src/pch.cpp | 14 + Kits/DirectXTK12/Src/pch.h | 78 + Kits/DirectXTK12/Src/vbo.h | 38 + .../SimplePlay3DSound.vcxproj | 1 - .../SimplePlaySound.vcxproj | 1 - .../SimpleWASAPICaptureUWP.vcxproj | 1 - .../SimpleWASAPIPlaySound.vcxproj | 1 - .../DirectXTKSimpleSample.cpp | 2 +- .../DirectXTKSimpleSample.vcxproj | 1 - .../Assets/Logo.png | Bin 0 -> 39826 bytes .../Assets/SmallLogo.png | Bin 0 -> 23704 bytes .../Assets/SplashScreen.png | Bin 0 -> 26474 bytes .../Assets/StoreLogo.png | Bin 0 -> 24268 bytes .../Assets/WideLogo.png | Bin 0 -> 46540 bytes .../Assets/seafloor.dds | Bin 0 -> 262272 bytes .../Assets/windowslogo.dds | Bin 0 -> 262272 bytes .../DeviceResources.cpp | 660 +++ .../DeviceResources.h | 117 + .../DirectXTKSimpleSample12.cpp | 500 +++ .../DirectXTKSimpleSample12.h | 110 + .../DirectXTKSimpleSample12.sln | 54 + .../DirectXTKSimpleSample12.vcxproj | 288 ++ .../DirectXTKSimpleSample12.vcxproj.filters | 80 + .../DirectXTKSimpleSample12_TemporaryKey.pfx | Bin 0 -> 2452 bytes .../DirectXTKSimpleSampleUWP12/Main.cpp | 382 ++ .../Package.appxmanifest | 49 + .../DirectXTKSimpleSampleUWP12/Readme.docx | Bin 0 -> 200483 bytes .../DirectXTKSimpleSampleUWP12/StepTimer.h | 188 + .../DirectXTKSimpleSampleUWP12/d3dx12.h | 1534 +++++++ .../DirectXTKSimpleSampleUWP12/pch.cpp | 10 + .../DirectXTKSimpleSampleUWP12/pch.h | 83 + .../SimpleBezierUWP/SimpleBezier.vcxproj | 1 - .../SimpleBezierUWP12/Assets/BezierDS.hlsl | 1 + .../Assets/BezierHS_fracEven.hlsl | 3 + .../Assets/BezierHS_fracOdd.hlsl | 3 + .../Assets/BezierHS_int.hlsl | 3 + .../SimpleBezierUWP12/Assets/BezierPS.hlsl | 1 + .../SimpleBezierUWP12/Assets/BezierVS.hlsl | 1 + .../SimpleBezierUWP12/Assets/Logo.png | Bin 0 -> 39826 bytes .../Assets/SimpleBezier.hlsli | 229 + .../SimpleBezierUWP12/Assets/SmallLogo.png | Bin 0 -> 23704 bytes .../Assets/SolidColorPS.hlsl | 1 + .../SimpleBezierUWP12/Assets/SplashScreen.png | Bin 0 -> 26474 bytes .../SimpleBezierUWP12/Assets/StoreLogo.png | Bin 0 -> 24268 bytes .../SimpleBezierUWP12/Assets/WideLogo.png | Bin 0 -> 46540 bytes .../SimpleBezierUWP12/DeviceResources.cpp | 658 +++ .../SimpleBezierUWP12/DeviceResources.h | 117 + .../IntroGraphics/SimpleBezierUWP12/Main.cpp | 357 ++ .../SimpleBezierUWP12/Package.appxmanifest | 49 + .../SimpleBezierUWP12/Readme.docx | Bin 0 -> 78231 bytes .../SimpleBezierUWP12/SimpleBezier.cpp | 548 +++ .../SimpleBezierUWP12/SimpleBezier.h | 111 + .../SimpleBezierUWP12/SimpleBezier.sln | 54 + .../SimpleBezierUWP12/SimpleBezier.vcxproj | 403 ++ .../SimpleBezier.vcxproj.filters | 95 + .../SimpleBezier_TemporaryKey.pfx | Bin 0 -> 2456 bytes .../SimpleBezierUWP12/StepTimer.h | 188 + .../IntroGraphics/SimpleBezierUWP12/d3dx12.h | 1534 +++++++ .../IntroGraphics/SimpleBezierUWP12/pch.cpp | 10 + Samples/IntroGraphics/SimpleBezierUWP12/pch.h | 70 + .../SimpleInstancing.vcxproj | 1 - .../SimpleLightingUWP/SimpleLighting.hlsli | 2 +- .../SimpleLightingUWP/SimpleLightingUWP.cpp | 11 +- .../SimpleLightingUWP/SimpleLightingUWP.sln | 2 +- .../SimpleLightingUWP12/Assets/Logo.png | Bin 0 -> 39826 bytes .../SimpleLightingUWP12/Assets/SmallLogo.png | Bin 0 -> 23704 bytes .../Assets/SplashScreen.png | Bin 0 -> 26474 bytes .../SimpleLightingUWP12/Assets/StoreLogo.png | Bin 0 -> 24268 bytes .../SimpleLightingUWP12/Assets/WideLogo.png | Bin 0 -> 46540 bytes .../SimpleLightingUWP12/DeviceResources.cpp | 658 +++ .../SimpleLightingUWP12/DeviceResources.h | 117 + .../SimpleLightingUWP12/LambertPS.hlsl | 2 + .../SimpleLightingUWP12/Main.cpp | 357 ++ .../SimpleLightingUWP12/Package.appxmanifest | 49 + .../SimpleLightingUWP12/Readme.docx | Bin 0 -> 80978 bytes .../SimpleLightingUWP12/SimpleLighting.hlsli | 80 + .../SimpleLightingUWP12.cpp | 582 +++ .../SimpleLightingUWP12/SimpleLightingUWP12.h | 127 + .../SimpleLightingUWP12.sln | 54 + .../SimpleLightingUWP12.vcxproj | 306 ++ .../SimpleLightingUWP12.vcxproj.filters | 83 + .../SimpleLightingUWP12_TemporaryKey.pfx | Bin 0 -> 2456 bytes .../SimpleLightingUWP12/SolidColorPS.hlsl | 2 + .../SimpleLightingUWP12/StepTimer.h | 188 + .../SimpleLightingUWP12/TriangleVS.hlsl | 2 + .../SimpleLightingUWP12/d3dx12.h | 1534 +++++++ .../IntroGraphics/SimpleLightingUWP12/pch.cpp | 10 + .../IntroGraphics/SimpleLightingUWP12/pch.h | 68 + .../SimpleTextureUWP/SimpleTextureUWP.vcxproj | 1 - .../SimpleTextureUWP12/DeviceResources.cpp | 4 + .../SimpleTextureUWP12/SimpleTextureUWP12.cpp | 4 + .../SimpleTextureUWP12/SimpleTextureUWP12.h | 3 + .../SimpleTextureUWP12/SimpleTextureUWP12.sln | 28 +- .../SimpleTextureUWP12.vcxproj | 23 +- .../IntroGraphics/SimpleTextureUWP12/pch.h | 1 + .../SimpleTriangleUWP.vcxproj | 1 - .../SimpleTriangleUWP12/DeviceResources.cpp | 4 + .../SimpleTriangleUWP12.cpp | 4 + .../SimpleTriangleUWP12/SimpleTriangleUWP12.h | 3 + .../SimpleTriangleUWP12.sln | 28 +- .../SimpleTriangleUWP12.vcxproj | 23 +- .../IntroGraphics/SimpleTriangleUWP12/pch.h | 1 + Samples/System/CPUSets/CPUSets.vcxproj | 1 - Samples/System/CollisionUWP/Collision.vcxproj | 1 - .../Common/Assets/Logo.png | Bin 0 -> 39826 bytes .../Common/Assets/SmallLogo.png | Bin 0 -> 23704 bytes .../Common/Assets/SplashScreen.png | Bin 0 -> 26474 bytes .../Common/Assets/StoreLogo.png | Bin 0 -> 24268 bytes .../Common/Assets/WideLogo.png | Bin 0 -> 46540 bytes .../Common/DeviceResources.cpp | 593 +++ .../Common/DeviceResources.h | 83 + .../ExtendedExecutionUWP/Common/StepTimer.h | 188 + .../ExtendedExecutionOnSuspend.cpp | 340 ++ .../ExtendedExecutionOnSuspend.h | 86 + .../ExtendedExecutionOnSuspend.vcxproj | 275 ++ ...ExtendedExecutionOnSuspend.vcxproj.filters | 75 + ...xtendedExecutionOnSuspend_TemporaryKey.pfx | Bin 0 -> 2452 bytes .../ExtendedExecutionOnSuspend/Main.cpp | 390 ++ .../Package.appxmanifest | 28 + .../ExtendedExecutionOnSuspend/pch.cpp | 10 + .../ExtendedExecutionOnSuspend/pch.h | 67 + .../ExtendedExecutionUWP.sln | 74 + .../PreemptiveExtendedExecution/Main.cpp | 388 ++ .../Package.appxmanifest | 28 + .../PreemptiveExtendedExecution.cpp | 345 ++ .../PreemptiveExtendedExecution.h | 90 + .../PreemptiveExtendedExecution.vcxproj | 277 ++ ...reemptiveExtendedExecution.vcxproj.filters | 75 + ...eemptiveExtendedExecution_TemporaryKey.pfx | Bin 0 -> 2452 bytes .../PreemptiveExtendedExecution/pch.cpp | 10 + .../PreemptiveExtendedExecution/pch.h | 67 + .../System/ExtendedExecutionUWP/Readme.docx | Bin 0 -> 1502096 bytes Samples/System/GamepadUWP/GamepadUWP.vcxproj | 1 - .../GamepadVibrationUWP.vcxproj | 1 - .../MemoryStatistics.vcxproj | 1 - .../System/MouseCursor/MouseCursor.vcxproj | 1 - .../NLSAndLocalizationUWP.vcxproj | 1 - .../System/SimplePLM_UWP/SimplePLM.vcxproj | 1 - .../System/SystemInfoUWP/SystemInfo.vcxproj | 1 - 418 files changed, 79632 insertions(+), 6909 deletions(-) create mode 100644 Kits/DirectXTK/Src/Geometry.cpp create mode 100644 Kits/DirectXTK/Src/Geometry.h create mode 100644 Kits/DirectXTK/Src/LoaderHelpers.h create mode 100644 Kits/DirectXTK/Src/SDKMesh.h create mode 100644 Kits/DirectXTK/Src/vbo.h create mode 100644 Kits/DirectXTK12/Audio/AudioEngine.cpp create mode 100644 Kits/DirectXTK12/Audio/DynamicSoundEffectInstance.cpp create mode 100644 Kits/DirectXTK12/Audio/SoundCommon.cpp create mode 100644 Kits/DirectXTK12/Audio/SoundCommon.h create mode 100644 Kits/DirectXTK12/Audio/SoundEffect.cpp create mode 100644 Kits/DirectXTK12/Audio/SoundEffectInstance.cpp create mode 100644 Kits/DirectXTK12/Audio/WAVFileReader.cpp create mode 100644 Kits/DirectXTK12/Audio/WAVFileReader.h create mode 100644 Kits/DirectXTK12/Audio/WaveBank.cpp create mode 100644 Kits/DirectXTK12/Audio/WaveBankReader.cpp create mode 100644 Kits/DirectXTK12/Audio/WaveBankReader.h create mode 100644 Kits/DirectXTK12/DirectXTK_Windows10.vcxproj create mode 100644 Kits/DirectXTK12/DirectXTK_Windows10.vcxproj.filters create mode 100644 Kits/DirectXTK12/Inc/Audio.h create mode 100644 Kits/DirectXTK12/Inc/CommonStates.h create mode 100644 Kits/DirectXTK12/Inc/DDSTextureLoader.h create mode 100644 Kits/DirectXTK12/Inc/DescriptorHeap.h create mode 100644 Kits/DirectXTK12/Inc/DirectXHelpers.h create mode 100644 Kits/DirectXTK12/Inc/Effects.h create mode 100644 Kits/DirectXTK12/Inc/GamePad.h create mode 100644 Kits/DirectXTK12/Inc/GeometricPrimitive.h create mode 100644 Kits/DirectXTK12/Inc/GraphicsMemory.h create mode 100644 Kits/DirectXTK12/Inc/Keyboard.h create mode 100644 Kits/DirectXTK12/Inc/Model.h create mode 100644 Kits/DirectXTK12/Inc/Mouse.h create mode 100644 Kits/DirectXTK12/Inc/PrimitiveBatch.h create mode 100644 Kits/DirectXTK12/Inc/RenderTargetState.h create mode 100644 Kits/DirectXTK12/Inc/ResourceUploadBatch.h create mode 100644 Kits/DirectXTK12/Inc/ScreenGrab.h create mode 100644 Kits/DirectXTK12/Inc/SimpleMath.h create mode 100644 Kits/DirectXTK12/Inc/SimpleMath.inl create mode 100644 Kits/DirectXTK12/Inc/SpriteBatch.h create mode 100644 Kits/DirectXTK12/Inc/SpriteFont.h create mode 100644 Kits/DirectXTK12/Inc/VertexTypes.h create mode 100644 Kits/DirectXTK12/Inc/WICTextureLoader.h create mode 100644 Kits/DirectXTK12/Readme.txt create mode 100644 Kits/DirectXTK12/Src/AlignedNew.h create mode 100644 Kits/DirectXTK12/Src/AlphaTestEffect.cpp create mode 100644 Kits/DirectXTK12/Src/BasicEffect.cpp create mode 100644 Kits/DirectXTK12/Src/Bezier.h create mode 100644 Kits/DirectXTK12/Src/BinaryReader.cpp create mode 100644 Kits/DirectXTK12/Src/BinaryReader.h create mode 100644 Kits/DirectXTK12/Src/CommonStates.cpp create mode 100644 Kits/DirectXTK12/Src/DDSTextureLoader.cpp create mode 100644 Kits/DirectXTK12/Src/DemandCreate.h create mode 100644 Kits/DirectXTK12/Src/DescriptorHeap.cpp create mode 100644 Kits/DirectXTK12/Src/DirectXHelpers.cpp create mode 100644 Kits/DirectXTK12/Src/DualTextureEffect.cpp create mode 100644 Kits/DirectXTK12/Src/EffectCommon.cpp create mode 100644 Kits/DirectXTK12/Src/EffectCommon.h create mode 100644 Kits/DirectXTK12/Src/EffectFactory.cpp create mode 100644 Kits/DirectXTK12/Src/EffectTextureFactory.cpp create mode 100644 Kits/DirectXTK12/Src/EnvironmentMapEffect.cpp create mode 100644 Kits/DirectXTK12/Src/GamePad.cpp create mode 100644 Kits/DirectXTK12/Src/GenericMultiBuffer.h create mode 100644 Kits/DirectXTK12/Src/GeometricPrimitive.cpp create mode 100644 Kits/DirectXTK12/Src/Geometry.cpp create mode 100644 Kits/DirectXTK12/Src/Geometry.h create mode 100644 Kits/DirectXTK12/Src/GraphicsMemory.cpp create mode 100644 Kits/DirectXTK12/Src/Keyboard.cpp create mode 100644 Kits/DirectXTK12/Src/LinearAllocator.cpp create mode 100644 Kits/DirectXTK12/Src/LinearAllocator.h create mode 100644 Kits/DirectXTK12/Src/LoaderHelpers.h create mode 100644 Kits/DirectXTK12/Src/Model.cpp create mode 100644 Kits/DirectXTK12/Src/ModelLoadSDKMESH.cpp create mode 100644 Kits/DirectXTK12/Src/ModelLoadVBO.cpp create mode 100644 Kits/DirectXTK12/Src/Mouse.cpp create mode 100644 Kits/DirectXTK12/Src/PlatformHelpers.h create mode 100644 Kits/DirectXTK12/Src/PrimitiveBatch.cpp create mode 100644 Kits/DirectXTK12/Src/ResourceUploadBatch.cpp create mode 100644 Kits/DirectXTK12/Src/SDKMesh.h create mode 100644 Kits/DirectXTK12/Src/ScreenGrab.cpp create mode 100644 Kits/DirectXTK12/Src/Shaders/AlphaTestEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/BasicEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/Common.fxh create mode 100644 Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasic.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasic.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/GenerateMips_main.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc create mode 100644 Kits/DirectXTK12/Src/Shaders/DualTextureEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/EnvironmentMapEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/GenerateMips.hlsl create mode 100644 Kits/DirectXTK12/Src/Shaders/Lighting.fxh create mode 100644 Kits/DirectXTK12/Src/Shaders/RootSig.fxh create mode 100644 Kits/DirectXTK12/Src/Shaders/SkinnedEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/SpriteEffect.fx create mode 100644 Kits/DirectXTK12/Src/Shaders/Structures.fxh create mode 100644 Kits/DirectXTK12/Src/SharedResourcePool.h create mode 100644 Kits/DirectXTK12/Src/SimpleMath.cpp create mode 100644 Kits/DirectXTK12/Src/SkinnedEffect.cpp create mode 100644 Kits/DirectXTK12/Src/SpriteBatch.cpp create mode 100644 Kits/DirectXTK12/Src/SpriteFont.cpp create mode 100644 Kits/DirectXTK12/Src/TeapotData.inc create mode 100644 Kits/DirectXTK12/Src/VertexTypes.cpp create mode 100644 Kits/DirectXTK12/Src/WICTextureLoader.cpp create mode 100644 Kits/DirectXTK12/Src/d3dx12.h create mode 100644 Kits/DirectXTK12/Src/dds.h create mode 100644 Kits/DirectXTK12/Src/pch.cpp create mode 100644 Kits/DirectXTK12/Src/pch.h create mode 100644 Kits/DirectXTK12/Src/vbo.h create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/Logo.png create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SmallLogo.png create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SplashScreen.png create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/StoreLogo.png create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/WideLogo.png create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/seafloor.dds create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/windowslogo.dds create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.cpp create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.h create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.sln create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj.filters create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12_TemporaryKey.pfx create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Package.appxmanifest create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/StepTimer.h create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/d3dx12.h create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.cpp create mode 100644 Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierDS.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracEven.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracOdd.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_int.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierPS.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierVS.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/Logo.png create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/SimpleBezier.hlsli create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/SmallLogo.png create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/SolidColorPS.hlsl create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/SplashScreen.png create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/StoreLogo.png create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Assets/WideLogo.png create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Package.appxmanifest create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.h create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.sln create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj.filters create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier_TemporaryKey.pfx create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/StepTimer.h create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/d3dx12.h create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/pch.cpp create mode 100644 Samples/IntroGraphics/SimpleBezierUWP12/pch.h create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Assets/Logo.png create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Assets/SmallLogo.png create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Assets/SplashScreen.png create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Assets/StoreLogo.png create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Assets/WideLogo.png create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/LambertPS.hlsl create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Package.appxmanifest create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLighting.hlsli create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.h create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.sln create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj.filters create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12_TemporaryKey.pfx create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/SolidColorPS.hlsl create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/StepTimer.h create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/TriangleVS.hlsl create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/d3dx12.h create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/pch.cpp create mode 100644 Samples/IntroGraphics/SimpleLightingUWP12/pch.h create mode 100644 Samples/System/ExtendedExecutionUWP/Common/Assets/Logo.png create mode 100644 Samples/System/ExtendedExecutionUWP/Common/Assets/SmallLogo.png create mode 100644 Samples/System/ExtendedExecutionUWP/Common/Assets/SplashScreen.png create mode 100644 Samples/System/ExtendedExecutionUWP/Common/Assets/StoreLogo.png create mode 100644 Samples/System/ExtendedExecutionUWP/Common/Assets/WideLogo.png create mode 100644 Samples/System/ExtendedExecutionUWP/Common/DeviceResources.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/Common/DeviceResources.h create mode 100644 Samples/System/ExtendedExecutionUWP/Common/StepTimer.h create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.h create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj.filters create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend_TemporaryKey.pfx create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Main.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Package.appxmanifest create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.h create mode 100644 Samples/System/ExtendedExecutionUWP/ExtendedExecutionUWP.sln create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Main.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Package.appxmanifest create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.h create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj.filters create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution_TemporaryKey.pfx create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/pch.cpp create mode 100644 Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/pch.h create mode 100644 Samples/System/ExtendedExecutionUWP/Readme.docx diff --git a/Kits/ATGTK/ControllerFont.h b/Kits/ATGTK/ControllerFont.h index 026075f0..0b560a0e 100644 --- a/Kits/ATGTK/ControllerFont.h +++ b/Kits/ATGTK/ControllerFont.h @@ -187,4 +187,219 @@ namespace DX textFont->DrawString(spriteBatch, strBuffer, outPos, color, 0.f, XMFLOAT2(0.f, 0.f), XMFLOAT2(scale, scale)); } } + + inline RECT XM_CALLCONV MeasureControllerDrawBounds(_In_ DirectX::SpriteFont* textFont, _In_ DirectX::SpriteFont* butnFont, + _In_z_ wchar_t const* text, DirectX::XMFLOAT2 const& position, float scale = 1) + { + using namespace DirectX; + + size_t textLen = wcslen(text); + if (textLen >= 4096) + { + throw std::out_of_range("String is too long"); + } + + float buttonHeight = butnFont->GetLineSpacing(); + float buttonScale = (textFont->GetLineSpacing() * scale) / buttonHeight; + float offsetY = buttonScale / 2.f; + + size_t j = 0; + wchar_t strBuffer[4096] = { 0 }; + + bool buttonText = false; + + XMFLOAT2 outPos = position; + + RECT result = { LONG_MAX, LONG_MAX, 0, 0 }; + for (size_t ch = 0; ch < textLen; ++ch) + { + if (buttonText) + { + strBuffer[j++] = text[ch]; + + if (text[ch] == L']') + { + wchar_t button[2] = { 0 }; + + if (_wcsicmp(strBuffer, L"[A]") == 0) + { + *button = static_cast(ControllerFont::AButton); + } + else if (_wcsicmp(strBuffer, L"[B]") == 0) + { + *button = static_cast(ControllerFont::BButton); + } + else if (_wcsicmp(strBuffer, L"[X]") == 0) + { + *button = static_cast(ControllerFont::XButton); + } + else if (_wcsicmp(strBuffer, L"[Y]") == 0) + { + *button = static_cast(ControllerFont::YButton); + } + else if (_wcsicmp(strBuffer, L"[DPad]") == 0) + { + *button = static_cast(ControllerFont::DPad); + } + else if (_wcsicmp(strBuffer, L"[View]") == 0) + { + *button = static_cast(ControllerFont::View); + } + else if (_wcsicmp(strBuffer, L"[Menu]") == 0) + { + *button = static_cast(ControllerFont::Menu); + } + else if (_wcsicmp(strBuffer, L"[Nexus]") == 0) + { + *button = static_cast(ControllerFont::Nexus); + } + else if (_wcsicmp(strBuffer, L"[RThumb]") == 0) + { + *button = static_cast(ControllerFont::RightThumb); + } + else if (_wcsicmp(strBuffer, L"[LThumb]") == 0) + { + *button = static_cast(ControllerFont::LeftThumb); + } + else if (_wcsicmp(strBuffer, L"[RB]") == 0) + { + *button = static_cast(ControllerFont::RightShoulder); + } + else if (_wcsicmp(strBuffer, L"[LB]") == 0) + { + *button = static_cast(ControllerFont::LeftShoulder); + } + else if (_wcsicmp(strBuffer, L"[RT]") == 0) + { + *button = static_cast(ControllerFont::RightTrigger); + } + else if (_wcsicmp(strBuffer, L"[LT]") == 0) + { + *button = static_cast(ControllerFont::LeftTrigger); + } + + if (*button) + { + float bsize = XMVectorGetX(butnFont->MeasureString(button)); + float offsetX = (bsize * buttonScale / 2.f); + + if (outPos.x < result.left) + result.left = long(outPos.x); + + if (outPos.y < result.top) + result.top = long(outPos.y); + + outPos.x += offsetX; + outPos.y -= offsetY; + + if (outPos.x < result.left) + result.left = long(outPos.x); + + if (outPos.y < result.top) + result.top = long(outPos.y); + + outPos.x += bsize * buttonScale; + outPos.y += offsetY; + + if (result.right < outPos.x) + result.right = long(outPos.x); + + if (result.bottom < outPos.y) + result.bottom = long(outPos.y); + } + + memset(strBuffer, 0, sizeof(strBuffer)); + j = 0; + + buttonText = false; + } + } + else + { + switch (text[ch]) + { + case '\r': + break; + + case '[': + if (*strBuffer) + { + if (outPos.x < result.left) + result.left = long(outPos.x); + + if (outPos.y < result.top) + result.top = long(outPos.y); + + outPos.x += XMVectorGetX(textFont->MeasureString(strBuffer)) * scale; + + if (result.right < outPos.x) + result.right = long(outPos.x); + + if (result.bottom < outPos.y) + result.bottom = long(outPos.y); + + memset(strBuffer, 0, sizeof(strBuffer)); + j = 0; + } + buttonText = true; + *strBuffer = L'['; + ++j; + break; + + case '\n': + if (*strBuffer) + { + if (outPos.x < result.left) + result.left = long(outPos.x); + + if (outPos.y < result.top) + result.top = long(outPos.y); + + outPos.x += XMVectorGetX(textFont->MeasureString(strBuffer)) * scale; + + if (result.right < outPos.x) + result.right = long(outPos.x); + + if (result.bottom < outPos.y) + result.bottom = long(outPos.y); + + memset(strBuffer, 0, sizeof(strBuffer)); + j = 0; + } + outPos.x = position.x; + outPos.y += textFont->GetLineSpacing() * scale; + break; + + default: + strBuffer[j++] = text[ch]; + break; + } + } + } + + if (*strBuffer) + { + if (outPos.x < result.left) + result.left = long(outPos.x); + + if (outPos.y < result.top) + result.top = long(outPos.y); + + outPos.x += XMVectorGetX(textFont->MeasureString(strBuffer)) * scale; + + if (result.right < outPos.x) + result.right = long(outPos.x); + + if (result.bottom < outPos.y) + result.bottom = long(outPos.y); + } + + if (result.left == LONG_MAX) + { + result.left = 0; + result.top = 0; + } + + return result; + } } \ No newline at end of file diff --git a/Kits/ATGTK/TextConsole.cpp b/Kits/ATGTK/TextConsole.cpp index a07887c8..6f4065f1 100644 --- a/Kits/ATGTK/TextConsole.cpp +++ b/Kits/ATGTK/TextConsole.cpp @@ -160,8 +160,8 @@ void TextConsole::SetWindow(const RECT& layout) float lineSpacing = m_font->GetLineSpacing(); unsigned int rows = std::max(1, static_cast(float(layout.bottom - layout.top) / lineSpacing)); - auto charSize = m_font->MeasureString(L"M"); - unsigned int columns = std::max(1, static_cast(float(layout.right - layout.left) / XMVectorGetX(charSize))); + RECT fontLayout = m_font->MeasureDrawBounds(L"X", XMFLOAT2(0,0)); + unsigned int columns = std::max(1, static_cast(float(layout.right - layout.left) / float(fontLayout.right - fontLayout.left))); std::unique_ptr buffer(new wchar_t[(columns + 1) * rows]); memset(buffer.get(), 0, sizeof(wchar_t) * (columns + 1) * rows); diff --git a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj index 647af28a..c5dce115 100644 --- a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj +++ b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj @@ -55,9 +55,13 @@ + + + + @@ -151,7 +155,6 @@ - @@ -176,6 +179,7 @@ + diff --git a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj.filters b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj.filters index 1c3428d2..d4f24f29 100644 --- a/Kits/DirectXTK/DirectXTK_Windows10.vcxproj.filters +++ b/Kits/DirectXTK/DirectXTK_Windows10.vcxproj.filters @@ -16,6 +16,15 @@ {fe608244-a8ad-4cca-b766-e82f3d32405b} + + {68d47991-3b63-4a17-a705-680374a426f2} + + + {b5728d91-918a-4481-8e6f-8e793da9ee2c} + + + {020af8ad-d3a0-41bc-bc05-b1d0a5d2a85f} + @@ -42,9 +51,6 @@ Inc - - Inc - Inc @@ -57,36 +63,15 @@ Inc - - Src - - - Src - - - Src - Src - - Src - - - Src - Src Src - - Src - - - Src - Audio @@ -99,38 +84,59 @@ Audio - + Inc + + Inc\Shared + - Inc + Inc\Shared - Inc + Inc\Shared - - Inc + + Inc\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared - - Inc - - - Src - - - Src\Shaders - Src\Shaders - - Src\Shaders - - - Src\Shaders - Src\Shaders @@ -419,8 +425,20 @@ Src\Shaders\Compiled + + Inc\Shared + - Src + Src\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared @@ -430,9 +448,6 @@ Src - - Src - Src @@ -481,9 +496,6 @@ Src - - Src - Src @@ -523,17 +535,26 @@ Audio - + Src + + Src\Shared + + + Src\Shared + - Src + Src\Shared - Src + Src\Shared - - Src + + Src\Shared + + + Src\Shared diff --git a/Kits/DirectXTK/Inc/GamePad.h b/Kits/DirectXTK/Inc/GamePad.h index 87a5fa55..88d87922 100644 --- a/Kits/DirectXTK/Inc/GamePad.h +++ b/Kits/DirectXTK/Inc/GamePad.h @@ -66,8 +66,16 @@ namespace DirectX bool rightStick; bool leftShoulder; bool rightShoulder; - bool back; - bool start; + union + { + bool back; + bool view; + }; + union + { + bool start; + bool menu; + }; }; struct DPad @@ -116,9 +124,9 @@ namespace DirectX bool __cdecl IsRightShoulderPressed() const { return buttons.rightShoulder; } bool __cdecl IsBackPressed() const { return buttons.back; } - bool __cdecl IsViewPressed() const { return buttons.back; } + bool __cdecl IsViewPressed() const { return buttons.view; } bool __cdecl IsStartPressed() const { return buttons.start; } - bool __cdecl IsMenuPressed() const { return buttons.start; } + bool __cdecl IsMenuPressed() const { return buttons.menu; } bool __cdecl IsDPadDownPressed() const { return dpad.down; }; bool __cdecl IsDPadUpPressed() const { return dpad.up; }; @@ -202,12 +210,27 @@ namespace DirectX ButtonState dpadLeft; ButtonState dpadRight; + ButtonState leftStickUp; + ButtonState leftStickDown; + ButtonState leftStickLeft; + ButtonState leftStickRight; + + ButtonState rightStickUp; + ButtonState rightStickDown; + ButtonState rightStickLeft; + ButtonState rightStickRight; + + ButtonState leftTrigger; + ButtonState rightTrigger; + ButtonStateTracker() { Reset(); } void __cdecl Update( const State& state ); void __cdecl Reset(); + State __cdecl GetLastState() const { return lastState; } + private: State lastState; }; diff --git a/Kits/DirectXTK/Inc/Keyboard.h b/Kits/DirectXTK/Inc/Keyboard.h index 2975d71a..d224f67d 100644 --- a/Kits/DirectXTK/Inc/Keyboard.h +++ b/Kits/DirectXTK/Inc/Keyboard.h @@ -440,6 +440,8 @@ namespace DirectX bool __cdecl IsKeyPressed(Keys key) const { return pressed.IsKeyDown(key); } bool __cdecl IsKeyReleased(Keys key) const { return released.IsKeyDown(key); } + State __cdecl GetLastState() const { return lastState; } + public: State lastState; }; diff --git a/Kits/DirectXTK/Inc/Mouse.h b/Kits/DirectXTK/Inc/Mouse.h index af081db4..6e04e3f5 100644 --- a/Kits/DirectXTK/Inc/Mouse.h +++ b/Kits/DirectXTK/Inc/Mouse.h @@ -76,6 +76,8 @@ namespace DirectX void __cdecl Reset(); + State __cdecl GetLastState() const { return lastState; } + private: State lastState; }; diff --git a/Kits/DirectXTK/Inc/PrimitiveBatch.h b/Kits/DirectXTK/Inc/PrimitiveBatch.h index 4632aefa..17dd451e 100644 --- a/Kits/DirectXTK/Inc/PrimitiveBatch.h +++ b/Kits/DirectXTK/Inc/PrimitiveBatch.h @@ -19,8 +19,8 @@ #include #endif -#include #include +#include #include @@ -74,7 +74,7 @@ namespace DirectX : PrimitiveBatchBase(std::move(moveFrom)) { } - PrimitiveBatch& __cdecl operator= (PrimitiveBatch&& moveFrom) + PrimitiveBatch& operator= (PrimitiveBatch&& moveFrom) { PrimitiveBatchBase::operator=(std::move(moveFrom)); return *this; @@ -82,7 +82,7 @@ namespace DirectX // Similar to the D3D9 API DrawPrimitiveUP. - void __cdecl Draw(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + void Draw(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) { void* mappedVertices; @@ -93,7 +93,7 @@ namespace DirectX // Similar to the D3D9 API DrawIndexedPrimitiveUP. - void __cdecl DrawIndexed(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + void DrawIndexed(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) { void* mappedVertices; @@ -103,7 +103,7 @@ namespace DirectX } - void __cdecl DrawLine(TVertex const& v1, TVertex const& v2) + void DrawLine(TVertex const& v1, TVertex const& v2) { TVertex* mappedVertices; @@ -114,7 +114,7 @@ namespace DirectX } - void __cdecl DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3) + void DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3) { TVertex* mappedVertices; @@ -126,7 +126,7 @@ namespace DirectX } - void __cdecl DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4) + void DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4) { static const uint16_t quadIndices[] = { 0, 1, 2, 0, 2, 3 }; diff --git a/Kits/DirectXTK/Inc/ScreenGrab.h b/Kits/DirectXTK/Inc/ScreenGrab.h index d4058e54..d530b9e1 100644 --- a/Kits/DirectXTK/Inc/ScreenGrab.h +++ b/Kits/DirectXTK/Inc/ScreenGrab.h @@ -38,13 +38,13 @@ namespace DirectX HRESULT __cdecl SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, - _In_z_ LPCWSTR fileName); + _In_z_ const wchar_t* fileName); HRESULT __cdecl SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _In_ REFGUID guidContainerFormat, - _In_z_ LPCWSTR fileName, + _In_z_ const wchar_t* fileName, _In_opt_ const GUID* targetFormat = nullptr, _In_opt_ std::function setCustomProps = nullptr); } \ No newline at end of file diff --git a/Kits/DirectXTK/Inc/SimpleMath.h b/Kits/DirectXTK/Inc/SimpleMath.h index 73a019dd..55a0e00f 100644 --- a/Kits/DirectXTK/Inc/SimpleMath.h +++ b/Kits/DirectXTK/Inc/SimpleMath.h @@ -13,13 +13,16 @@ #pragma once -#if defined(_XBOX_ONE) && defined(_TITLE) -#include -#else -#include +#if !defined(__d3d11_h__) && !defined(__d3d11_x_h__) && !defined(__d3d12_h__) && !defined(__d3d12_x_h__) +#error include d3d11.h or d3d12.h before including SimpleMath.h +#endif + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#include #endif #include +#include #include #include @@ -825,14 +828,30 @@ public: width(float(rct.right - rct.left)), height(float(rct.bottom - rct.top)), minDepth(0.f), maxDepth(1.f) {} + +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) + // Direct3D 11 interop explicit Viewport(const D3D11_VIEWPORT& vp) : x(vp.TopLeftX), y(vp.TopLeftY), width(vp.Width), height(vp.Height), minDepth(vp.MinDepth), maxDepth(vp.MaxDepth) {} - // Direct3D 11 interop operator D3D11_VIEWPORT() { return *reinterpret_cast(this); } const D3D11_VIEWPORT* Get11() const { return reinterpret_cast(this); } + Viewport& operator= (const D3D11_VIEWPORT& vp); +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) + // Direct3D 12 interop + explicit Viewport(const D3D12_VIEWPORT& vp) : + x(vp.TopLeftX), y(vp.TopLeftY), + width(vp.Width), height(vp.Height), + minDepth(vp.MinDepth), maxDepth(vp.MaxDepth) {} + + operator D3D12_VIEWPORT() { return *reinterpret_cast(this); } + const D3D12_VIEWPORT* Get12() const { return reinterpret_cast(this); } + Viewport& operator= (const D3D12_VIEWPORT& vp); +#endif // Comparison operators bool operator == ( const Viewport& vp ) const; @@ -841,7 +860,6 @@ public: // Assignment operators Viewport& operator= (const Viewport& vp); Viewport& operator= (const RECT& rct); - Viewport& operator= (const D3D11_VIEWPORT& vp); // Viewport operations float AspectRatio() const; diff --git a/Kits/DirectXTK/Inc/SimpleMath.inl b/Kits/DirectXTK/Inc/SimpleMath.inl index f8caace8..1be0a5fc 100644 --- a/Kits/DirectXTK/Inc/SimpleMath.inl +++ b/Kits/DirectXTK/Inc/SimpleMath.inl @@ -3633,6 +3633,7 @@ inline Viewport& Viewport::operator= (const RECT& rct) return *this; } +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) inline Viewport& Viewport::operator= (const D3D11_VIEWPORT& vp) { x = vp.TopLeftX; y = vp.TopLeftY; @@ -3640,6 +3641,17 @@ inline Viewport& Viewport::operator= (const D3D11_VIEWPORT& vp) minDepth = vp.MinDepth; maxDepth = vp.MaxDepth; return *this; } +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +inline Viewport& Viewport::operator= (const D3D12_VIEWPORT& vp) +{ + x = vp.TopLeftX; y = vp.TopLeftY; + width = vp.Width; height = vp.Height; + minDepth = vp.MinDepth; maxDepth = vp.MaxDepth; + return *this; +} +#endif //------------------------------------------------------------------------------ // Viewport operations diff --git a/Kits/DirectXTK/Inc/SpriteFont.h b/Kits/DirectXTK/Inc/SpriteFont.h index a3a0f969..cdca6e53 100644 --- a/Kits/DirectXTK/Inc/SpriteFont.h +++ b/Kits/DirectXTK/Inc/SpriteFont.h @@ -42,6 +42,9 @@ namespace DirectX XMVECTOR XM_CALLCONV MeasureString(_In_z_ wchar_t const* text) const; + RECT __cdecl MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position) const; + RECT XM_CALLCONV MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position) const; + // Spacing properties float __cdecl GetLineSpacing() const; void __cdecl SetLineSpacing(float spacing); @@ -54,7 +57,7 @@ namespace DirectX // Custom layout/rendering Glyph const* __cdecl FindGlyph(wchar_t character) const; - void GetSpriteSheet( ID3D11ShaderResourceView** texture ) const; + void __cdecl GetSpriteSheet( ID3D11ShaderResourceView** texture ) const; // Describes a single character glyph. struct Glyph diff --git a/Kits/DirectXTK/Readme.txt b/Kits/DirectXTK/Readme.txt index bbf8bc2c..9f81dde4 100644 --- a/Kits/DirectXTK/Readme.txt +++ b/Kits/DirectXTK/Readme.txt @@ -1,10 +1,10 @@ --------------------------------- -DirectXTK - the DirectX Tool Kit --------------------------------- +----------------------------------------------- +DirectXTK - the DirectX Tool Kit for DirectX 11 +----------------------------------------------- Copyright (c) Microsoft Corporation. All rights reserved. -May 31, 2016 +June 30, 2016 This package contains the "DirectX Tool Kit", a collection of helper classes for writing Direct3D 11 C++ code for Universal Windows Platform (UWP) apps for Windows 10, @@ -13,7 +13,7 @@ Windows 8.x Win32 desktop applications, Windows 7 applications, and Windows Vista Direct3D 11.0 applications. This code is designed to build with Visual Studio 2013 or 2015. It is recommended that you -make use of VS 2013 Update 5, VS 2015 Update 2, and Windows 7 Service Pack 1 or later. +make use of VS 2013 Update 5 or VS 2015 Update 3 and Windows 7 Service Pack 1 or later. These components are designed to work without requiring any content from the DirectX SDK. For details, see "Where is the DirectX SDK?" . @@ -69,11 +69,24 @@ Note: Xbox One exclusive apps developers using the Xbox One XDK need to generate FXC compiler from the Xbox One XDK. While they will continue to work if outdated, a mismatch will cause runtime compilation overhead that would otherwise be avoided. +This project has adopted the Microsoft Open Source Code of Conduct. For more information see the +Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments. + +https://opensource.microsoft.com/codeofconduct/ + --------------- RELEASE HISTORY --------------- +June 30, 2016 + MesaureDrawString added to SpriteFont; bad fix to MeasureString reverted + GamePad tracker updated to track emulated buttons (i.e. leftStickUp) + EffectFactory SetDirectory now checks current working directory (CWD) as well + *breaking change* must include before including + Code refactor for sharing some files with DirectX 12 version + Minor code cleanup + May 31, 2016 Added VertexPosition and VertexPositionDualTexture to VertexTypes Xbox One platform fix for PrimitiveBatch diff --git a/Kits/DirectXTK/Src/DDSTextureLoader.cpp b/Kits/DirectXTK/Src/DDSTextureLoader.cpp index 9acdd586..5e4d003e 100644 --- a/Kits/DirectXTK/Src/DDSTextureLoader.cpp +++ b/Kits/DirectXTK/Src/DDSTextureLoader.cpp @@ -25,707 +25,18 @@ #include "dds.h" #include "DirectXHelpers.h" #include "PlatformHelpers.h" +#include "LoaderHelpers.h" using namespace DirectX; +static_assert(DDS_DIMENSION_TEXTURE1D == D3D11_RESOURCE_DIMENSION_TEXTURE1D, "dds mismatch"); +static_assert(DDS_DIMENSION_TEXTURE2D == D3D11_RESOURCE_DIMENSION_TEXTURE2D, "dds mismatch"); +static_assert(DDS_DIMENSION_TEXTURE3D == D3D11_RESOURCE_DIMENSION_TEXTURE3D, "dds mismatch"); +static_assert(DDS_RESOURCE_MISC_TEXTURECUBE == D3D11_RESOURCE_MISC_TEXTURECUBE, "dds mismatch"); + namespace { //-------------------------------------------------------------------------------------- - HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t* fileName, - std::unique_ptr& ddsData, - DDS_HEADER** header, - uint8_t** bitData, - size_t* bitSize - ) - { - if (!header || !bitData || !bitSize) - { - return E_POINTER; - } - - // open the file -#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) - ScopedHandle hFile(safe_handle(CreateFile2(fileName, - GENERIC_READ, - FILE_SHARE_READ, - OPEN_EXISTING, - nullptr))); -#else - ScopedHandle hFile(safe_handle(CreateFileW(fileName, - GENERIC_READ, - FILE_SHARE_READ, - nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - nullptr))); -#endif - - if (!hFile) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - // Get the file size - FILE_STANDARD_INFO fileInfo; - if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - // File is too big for 32-bit allocation, so reject read - if (fileInfo.EndOfFile.HighPart > 0) - { - return E_FAIL; - } - - // Need at least enough data to fill the header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) - { - return E_FAIL; - } - - // create enough space for the file data - ddsData.reset(new (std::nothrow) uint8_t[ fileInfo.EndOfFile.LowPart ]); - if (!ddsData) - { - return E_OUTOFMEMORY; - } - - // read the data in - DWORD BytesRead = 0; - if (!ReadFile(hFile.get(), - ddsData.get(), - fileInfo.EndOfFile.LowPart, - &BytesRead, - nullptr - )) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - if (BytesRead < fileInfo.EndOfFile.LowPart) - { - return E_FAIL; - } - - // DDS files always start with the same magic number ("DDS ") - uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); - if (dwMagicNumber != DDS_MAGIC) - { - return E_FAIL; - } - - auto hdr = reinterpret_cast(ddsData.get() + sizeof(uint32_t)); - - // Verify header to validate DDS file - if (hdr->size != sizeof(DDS_HEADER) || - hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) - { - return E_FAIL; - } - - // Check for DX10 extension - bool bDXT10Header = false; - if ((hdr->ddspf.flags & DDS_FOURCC) && - (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) - { - // Must be long enough for both headers and magic value - if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) - { - return E_FAIL; - } - - bDXT10Header = true; - } - - // setup the pointers in the process request - *header = hdr; - ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER) - + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0); - *bitData = ddsData.get() + offset; - *bitSize = fileInfo.EndOfFile.LowPart - offset; - - return S_OK; - } - - //-------------------------------------------------------------------------------------- - // Return the BPP for a particular format - //-------------------------------------------------------------------------------------- - size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) - { - switch (fmt) - { - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_UINT: - case DXGI_FORMAT_R32G32B32A32_SINT: - return 128; - - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_UINT: - case DXGI_FORMAT_R32G32B32_SINT: - return 96; - - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - case DXGI_FORMAT_Y416: - case DXGI_FORMAT_Y210: - case DXGI_FORMAT_Y216: - return 64; - - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_AYUV: - case DXGI_FORMAT_Y410: - case DXGI_FORMAT_YUY2: - return 32; - - case DXGI_FORMAT_P010: - case DXGI_FORMAT_P016: - return 24; - - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_A8P8: - case DXGI_FORMAT_B4G4R4A4_UNORM: - return 16; - - case DXGI_FORMAT_NV12: - case DXGI_FORMAT_420_OPAQUE: - case DXGI_FORMAT_NV11: - return 12; - - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_AI44: - case DXGI_FORMAT_IA44: - case DXGI_FORMAT_P8: - return 8; - - case DXGI_FORMAT_R1_UNORM: - return 1; - - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - return 4; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - -#if defined(_XBOX_ONE) && defined(_TITLE) - - case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: - case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: - case DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: - return 32; - - case DXGI_FORMAT_D16_UNORM_S8_UINT: - case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X16_TYPELESS_G8_UINT: - return 24; - - case DXGI_FORMAT_R4G4_UNORM: - return 8; - -#endif // _XBOX_ONE && _TITLE - - default: - return 0; - } - } - - //-------------------------------------------------------------------------------------- - // Get surface information for a particular format - //-------------------------------------------------------------------------------------- - void GetSurfaceInfo(_In_ size_t width, - _In_ size_t height, - _In_ DXGI_FORMAT fmt, - _Out_opt_ size_t* outNumBytes, - _Out_opt_ size_t* outRowBytes, - _Out_opt_ size_t* outNumRows) - { - size_t numBytes = 0; - size_t rowBytes = 0; - size_t numRows = 0; - - bool bc = false; - bool packed = false; - bool planar = false; - size_t bpe = 0; - switch (fmt) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - bc = true; - bpe = 8; - break; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - bc = true; - bpe = 16; - break; - - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_YUY2: - packed = true; - bpe = 4; - break; - - case DXGI_FORMAT_Y210: - case DXGI_FORMAT_Y216: - packed = true; - bpe = 8; - break; - - case DXGI_FORMAT_NV12: - case DXGI_FORMAT_420_OPAQUE: - planar = true; - bpe = 2; - break; - - case DXGI_FORMAT_P010: - case DXGI_FORMAT_P016: - planar = true; - bpe = 4; - break; - -#if defined(_XBOX_ONE) && defined(_TITLE) - - case DXGI_FORMAT_D16_UNORM_S8_UINT: - case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X16_TYPELESS_G8_UINT: - planar = true; - bpe = 4; - break; - -#endif - } - - if (bc) - { - size_t numBlocksWide = 0; - if (width > 0) - { - numBlocksWide = std::max(1, (width + 3) / 4); - } - size_t numBlocksHigh = 0; - if (height > 0) - { - numBlocksHigh = std::max(1, (height + 3) / 4); - } - rowBytes = numBlocksWide * bpe; - numRows = numBlocksHigh; - numBytes = rowBytes * numBlocksHigh; - } - else if (packed) - { - rowBytes = ((width + 1) >> 1) * bpe; - numRows = height; - numBytes = rowBytes * height; - } - else if (fmt == DXGI_FORMAT_NV11) - { - rowBytes = ((width + 3) >> 2) * 4; - numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data - numBytes = rowBytes * numRows; - } - else if (planar) - { - rowBytes = ((width + 1) >> 1) * bpe; - numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1); - numRows = height + ((height + 1) >> 1); - } - else - { - size_t bpp = BitsPerPixel(fmt); - rowBytes = (width * bpp + 7) / 8; // round up to nearest byte - numRows = height; - numBytes = rowBytes * height; - } - - if (outNumBytes) - { - *outNumBytes = numBytes; - } - if (outRowBytes) - { - *outRowBytes = rowBytes; - } - if (outNumRows) - { - *outNumRows = numRows; - } - } - - //-------------------------------------------------------------------------------------- - #define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a ) - - DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf) - { - if (ddpf.flags & DDS_RGB) - { - // Note that sRGB formats are written using the "DX10" extended header - - switch (ddpf.RGBBitCount) - { - case 32: - if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) - { - return DXGI_FORMAT_R8G8B8A8_UNORM; - } - - if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) - { - return DXGI_FORMAT_B8G8R8A8_UNORM; - } - - if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000)) - { - return DXGI_FORMAT_B8G8R8X8_UNORM; - } - - // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8 - - // Note that many common DDS reader/writers (including D3DX) swap the - // the RED/BLUE masks for 10:10:10:2 formats. We assume - // below that the 'backwards' header mask is being used since it is most - // likely written by D3DX. The more robust solution is to use the 'DX10' - // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly - - // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data - if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000)) - { - return DXGI_FORMAT_R10G10B10A2_UNORM; - } - - // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10 - - if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) - { - return DXGI_FORMAT_R16G16_UNORM; - } - - if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000)) - { - // Only 32-bit color channel format in D3D9 was R32F - return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 - } - break; - - case 24: - // No 24bpp DXGI formats aka D3DFMT_R8G8B8 - break; - - case 16: - if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000)) - { - return DXGI_FORMAT_B5G5R5A1_UNORM; - } - if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000)) - { - return DXGI_FORMAT_B5G6R5_UNORM; - } - - // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5 - - if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000)) - { - return DXGI_FORMAT_B4G4R4A4_UNORM; - } - - // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4 - - // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc. - break; - } - } - else if (ddpf.flags & DDS_LUMINANCE) - { - if (8 == ddpf.RGBBitCount) - { - if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000)) - { - return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension - } - - // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 - } - - if (16 == ddpf.RGBBitCount) - { - if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000)) - { - return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension - } - if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) - { - return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension - } - } - } - else if (ddpf.flags & DDS_ALPHA) - { - if (8 == ddpf.RGBBitCount) - { - return DXGI_FORMAT_A8_UNORM; - } - } - else if (ddpf.flags & DDS_BUMPDUDV) - { - if (16 == ddpf.RGBBitCount) - { - if (ISBITMASK(0x00ff, 0xff00, 0x0000, 0x0000)) - { - return DXGI_FORMAT_R8G8_SNORM; // D3DX10/11 writes this out as DX10 extension - } - } - - if (32 == ddpf.RGBBitCount) - { - if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) - { - return DXGI_FORMAT_R8G8B8A8_SNORM; // D3DX10/11 writes this out as DX10 extension - } - if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) - { - return DXGI_FORMAT_R16G16_SNORM; // D3DX10/11 writes this out as DX10 extension - } - - // No DXGI format maps to ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) aka D3DFMT_A2W10V10U10 - } - } - else if (ddpf.flags & DDS_FOURCC) - { - if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC) - { - return DXGI_FORMAT_BC1_UNORM; - } - if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC) - { - return DXGI_FORMAT_BC2_UNORM; - } - if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC) - { - return DXGI_FORMAT_BC3_UNORM; - } - - // While pre-multiplied alpha isn't directly supported by the DXGI formats, - // they are basically the same as these BC formats so they can be mapped - if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC) - { - return DXGI_FORMAT_BC2_UNORM; - } - if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC) - { - return DXGI_FORMAT_BC3_UNORM; - } - - if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC) - { - return DXGI_FORMAT_BC4_UNORM; - } - if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC) - { - return DXGI_FORMAT_BC4_UNORM; - } - if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC) - { - return DXGI_FORMAT_BC4_SNORM; - } - - if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC) - { - return DXGI_FORMAT_BC5_UNORM; - } - if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC) - { - return DXGI_FORMAT_BC5_UNORM; - } - if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC) - { - return DXGI_FORMAT_BC5_SNORM; - } - - // BC6H and BC7 are written using the "DX10" extended header - - if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC) - { - return DXGI_FORMAT_R8G8_B8G8_UNORM; - } - if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC) - { - return DXGI_FORMAT_G8R8_G8B8_UNORM; - } - - if (MAKEFOURCC('Y', 'U', 'Y', '2') == ddpf.fourCC) - { - return DXGI_FORMAT_YUY2; - } - - // Check for D3DFORMAT enums being set here - switch (ddpf.fourCC) - { - case 36: // D3DFMT_A16B16G16R16 - return DXGI_FORMAT_R16G16B16A16_UNORM; - - case 110: // D3DFMT_Q16W16V16U16 - return DXGI_FORMAT_R16G16B16A16_SNORM; - - case 111: // D3DFMT_R16F - return DXGI_FORMAT_R16_FLOAT; - - case 112: // D3DFMT_G16R16F - return DXGI_FORMAT_R16G16_FLOAT; - - case 113: // D3DFMT_A16B16G16R16F - return DXGI_FORMAT_R16G16B16A16_FLOAT; - - case 114: // D3DFMT_R32F - return DXGI_FORMAT_R32_FLOAT; - - case 115: // D3DFMT_G32R32F - return DXGI_FORMAT_R32G32_FLOAT; - - case 116: // D3DFMT_A32B32G32R32F - return DXGI_FORMAT_R32G32B32A32_FLOAT; - } - } - - return DXGI_FORMAT_UNKNOWN; - } - - //-------------------------------------------------------------------------------------- - DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) - { - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - - case DXGI_FORMAT_BC1_UNORM: - return DXGI_FORMAT_BC1_UNORM_SRGB; - - case DXGI_FORMAT_BC2_UNORM: - return DXGI_FORMAT_BC2_UNORM_SRGB; - - case DXGI_FORMAT_BC3_UNORM: - return DXGI_FORMAT_BC3_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8X8_UNORM: - return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; - - case DXGI_FORMAT_BC7_UNORM: - return DXGI_FORMAT_BC7_UNORM_SRGB; - - default: - return format; - } - } - - //-------------------------------------------------------------------------------------- - template HRESULT FillInitData(_In_ size_t width, _In_ size_t height, _In_ size_t depth, @@ -739,7 +50,7 @@ namespace _Out_ size_t& theight, _Out_ size_t& tdepth, _Out_ size_t& skipMip, - _Out_writes_(mipCount*arraySize) SubresourceStructType* initData) + _Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA* initData) { if (!bitData || !initData) { @@ -1486,34 +797,6 @@ namespace return hr; } - - //-------------------------------------------------------------------------------------- - DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) - { - if (header->ddspf.flags & DDS_FOURCC) - { - if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC) - { - auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); - auto mode = static_cast(d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK); - switch (mode) - { - case DDS_ALPHA_MODE_STRAIGHT: - case DDS_ALPHA_MODE_PREMULTIPLIED: - case DDS_ALPHA_MODE_OPAQUE: - case DDS_ALPHA_MODE_CUSTOM: - return mode; - } - } - else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC) - || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC)) - { - return DDS_ALPHA_MODE_PREMULTIPLIED; - } - } - - return DDS_ALPHA_MODE_UNKNOWN; - } } // anonymous namespace diff --git a/Kits/DirectXTK/Src/DGSLEffectFactory.cpp b/Kits/DirectXTK/Src/DGSLEffectFactory.cpp index 2991b7f9..983b63f1 100644 --- a/Kits/DirectXTK/Src/DGSLEffectFactory.cpp +++ b/Kits/DirectXTK/Src/DGSLEffectFactory.cpp @@ -351,6 +351,18 @@ void DGSLEffectFactory::Impl::CreateTexture( const wchar_t* name, ID3D11DeviceCo wcscpy_s( fullName, mPath ); wcscat_s( fullName, name ); + WIN32_FILE_ATTRIBUTE_DATA fileAttr = {}; + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + // Try Current Working Directory (CWD) + wcscpy_s( fullName, name ); + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + DebugTrace( "DGSLEffectFactory could not find texture file '%ls'\n", name ); + throw std::exception( "CreateTexture" ); + } + } + wchar_t ext[_MAX_EXT]; _wsplitpath_s( name, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT ); @@ -414,6 +426,18 @@ void DGSLEffectFactory::Impl::CreatePixelShader( const wchar_t* name, ID3D11Pixe wcscpy_s( fullName, mPath ); wcscat_s( fullName, name ); + WIN32_FILE_ATTRIBUTE_DATA fileAttr = {}; + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + // Try Current Working Directory (CWD) + wcscpy_s( fullName, name ); + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + DebugTrace( "DGSLEffectFactory could not find shader file '%ls'\n", name ); + throw std::exception( "CreatePixelShader" ); + } + } + size_t dataSize = 0; std::unique_ptr data; HRESULT hr = BinaryReader::ReadEntireFile( fullName, data, &dataSize ); diff --git a/Kits/DirectXTK/Src/EffectFactory.cpp b/Kits/DirectXTK/Src/EffectFactory.cpp index 579285ad..d6da13f9 100644 --- a/Kits/DirectXTK/Src/EffectFactory.cpp +++ b/Kits/DirectXTK/Src/EffectFactory.cpp @@ -265,6 +265,18 @@ void EffectFactory::Impl::CreateTexture( const wchar_t* name, ID3D11DeviceContex wcscpy_s( fullName, mPath ); wcscat_s( fullName, name ); + WIN32_FILE_ATTRIBUTE_DATA fileAttr = {}; + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + // Try Current Working Directory (CWD) + wcscpy_s( fullName, name ); + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + DebugTrace( "EffectFactory could not find texture file '%ls'\n", name ); + throw std::exception( "CreateTexture" ); + } + } + wchar_t ext[_MAX_EXT]; _wsplitpath_s( name, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT ); diff --git a/Kits/DirectXTK/Src/GamePad.cpp b/Kits/DirectXTK/Src/GamePad.cpp index 75e1caf0..5475f1d2 100644 --- a/Kits/DirectXTK/Src/GamePad.cpp +++ b/Kits/DirectXTK/Src/GamePad.cpp @@ -1195,6 +1195,38 @@ void GamePad::ButtonStateTracker::Update( const GamePad::State& state ) assert( ( !state.dpad.up && lastState.dpad.up ) == ( dpadUp == RELEASED ) ); assert( ( state.dpad.up && !lastState.dpad.up ) == ( dpadUp == PRESSED ) ); + // Handle 'threshold' tests which emulate buttons + + bool threshold = state.IsLeftThumbStickUp(); + leftStickUp = static_cast( ( !!threshold) | ( ( !!threshold ^ !!lastState.IsLeftThumbStickUp() ) << 1 ) ); + + threshold = state.IsLeftThumbStickDown(); + leftStickDown = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickDown()) << 1)); + + threshold = state.IsLeftThumbStickLeft(); + leftStickLeft = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickLeft()) << 1)); + + threshold = state.IsLeftThumbStickRight(); + leftStickRight = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickRight()) << 1)); + + threshold = state.IsRightThumbStickUp(); + rightStickUp = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickUp()) << 1)); + + threshold = state.IsRightThumbStickDown(); + rightStickDown = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickDown()) << 1)); + + threshold = state.IsRightThumbStickLeft(); + rightStickLeft = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickLeft()) << 1)); + + threshold = state.IsRightThumbStickRight(); + rightStickRight = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickRight()) << 1)); + + threshold = state.IsLeftTriggerPressed(); + leftTrigger = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftTriggerPressed()) << 1)); + + threshold = state.IsRightTriggerPressed(); + rightTrigger = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightTriggerPressed()) << 1)); + lastState = state; } diff --git a/Kits/DirectXTK/Src/GeometricPrimitive.cpp b/Kits/DirectXTK/Src/GeometricPrimitive.cpp index 0b9a9976..df30dfe4 100644 --- a/Kits/DirectXTK/Src/GeometricPrimitive.cpp +++ b/Kits/DirectXTK/Src/GeometricPrimitive.cpp @@ -16,11 +16,8 @@ #include "Effects.h" #include "CommonStates.h" #include "DirectXHelpers.h" -#include "VertexTypes.h" #include "SharedResourcePool.h" -#include "Bezier.h" - -#include +#include "Geometry.h" using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -28,58 +25,6 @@ using Microsoft::WRL::ComPtr; namespace { - static const float SQRT2 = 1.41421356237309504880f; - static const float SQRT3 = 1.73205080756887729352f; - static const float SQRT6 = 2.44948974278317809820f; - - - void CheckIndexOverflow(size_t value) - { - // Use >=, not > comparison, because some D3D level 9_x hardware does not support 0xFFFF index values. - if (value >= USHRT_MAX) - throw std::exception("Index value out of range: cannot tesselate primitive so finely"); - } - - - // Collection types used when generating the geometry. - typedef std::vector VertexCollection; - typedef std::vector IndexCollection; - - inline void index_push_back(IndexCollection& indices, size_t value) - { - CheckIndexOverflow(value); - indices.push_back((uint16_t)value); - } - - - // Helper for flipping winding of geometric primitives for LH vs. RH coords - static void ReverseWinding( IndexCollection& indices, VertexCollection& vertices ) - { - assert( (indices.size() % 3) == 0 ); - for( auto it = indices.begin(); it != indices.end(); it += 3 ) - { - std::swap( *it, *(it+2) ); - } - - for( auto it = vertices.begin(); it != vertices.end(); ++it ) - { - it->textureCoordinate.x = ( 1.f - it->textureCoordinate.x ); - } - } - - - // Helper for inverting normals of geometric primitives for 'inside' vs. 'outside' viewing - static void InvertNormals( VertexCollection& vertices ) - { - for( auto it = vertices.begin(); it != vertices.end(); ++it ) - { - it->normal.x = -it->normal.x; - it->normal.y = -it->normal.y; - it->normal.z = -it->normal.z; - } - } - - // Helper for creating a D3D vertex or index buffer. template static void CreateBuffer(_In_ ID3D11Device* device, T const& data, D3D11_BIND_FLAG bindFlags, _Outptr_ ID3D11Buffer** pBuffer) @@ -107,7 +52,7 @@ namespace // Helper for creating a D3D input layout. - static void CreateInputLayout(_In_ ID3D11Device* device, IEffect* effect, _Outptr_ ID3D11InputLayout** pInputLayout) + void CreateInputLayout(_In_ ID3D11Device* device, IEffect* effect, _Outptr_ ID3D11InputLayout** pInputLayout) { assert( pInputLayout != 0 ); @@ -398,12 +343,21 @@ void GeometricPrimitive::CreateInputLayout(IEffect* effect, ID3D11InputLayout** // Creates a cube primitive. std::unique_ptr GeometricPrimitive::CreateCube(_In_ ID3D11DeviceContext* deviceContext, float size, bool rhcoords) { - return CreateBox(deviceContext, XMFLOAT3(size,size,size), rhcoords); + VertexCollection vertices; + IndexCollection indices; + ComputeBox(vertices, indices, XMFLOAT3(size, size, size), rhcoords, false); + + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + primitive->pImpl->Initialize(deviceContext, vertices, indices); + + return primitive; } void GeometricPrimitive::CreateCube(std::vector& vertices, std::vector& indices, float size, bool rhcoords) { - return CreateBox(vertices, indices, XMFLOAT3(size,size,size), rhcoords); + ComputeBox(vertices, indices, XMFLOAT3(size,size,size), rhcoords, false); } @@ -412,7 +366,7 @@ std::unique_ptr GeometricPrimitive::CreateBox(_In_ ID3D11Dev { VertexCollection vertices; IndexCollection indices; - CreateBox(vertices, indices, size, rhcoords, invertn); + ComputeBox(vertices, indices, size, rhcoords, invertn); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -424,67 +378,7 @@ std::unique_ptr GeometricPrimitive::CreateBox(_In_ ID3D11Dev void GeometricPrimitive::CreateBox(std::vector& vertices, std::vector& indices, const XMFLOAT3& size, bool rhcoords, bool invertn) { - vertices.clear(); - indices.clear(); - - // A box has six faces, each one pointing in a different direction. - const int FaceCount = 6; - - static const XMVECTORF32 faceNormals[FaceCount] = - { - { 0, 0, 1 }, - { 0, 0, -1 }, - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 1, 0 }, - { 0, -1, 0 }, - }; - - static const XMVECTORF32 textureCoordinates[4] = - { - { 1, 0 }, - { 1, 1 }, - { 0, 1 }, - { 0, 0 }, - }; - - XMVECTOR tsize = XMLoadFloat3(&size); - tsize = XMVectorDivide(tsize, g_XMTwo); - - // Create each face in turn. - for (int i = 0; i < FaceCount; i++) - { - XMVECTOR normal = faceNormals[i]; - - // Get two vectors perpendicular both to the face normal and to each other. - XMVECTOR basis = (i >= 4) ? g_XMIdentityR2 : g_XMIdentityR1; - - XMVECTOR side1 = XMVector3Cross(normal, basis); - XMVECTOR side2 = XMVector3Cross(normal, side1); - - // Six indices (two triangles) per face. - size_t vbase = vertices.size(); - index_push_back(indices, vbase + 0); - index_push_back(indices, vbase + 1); - index_push_back(indices, vbase + 2); - - index_push_back(indices, vbase + 0); - index_push_back(indices, vbase + 2); - index_push_back(indices, vbase + 3); - - // Four vertices per face. - vertices.push_back(VertexPositionNormalTexture((normal - side1 - side2) * tsize, normal, textureCoordinates[0])); - vertices.push_back(VertexPositionNormalTexture((normal - side1 + side2) * tsize, normal, textureCoordinates[1])); - vertices.push_back(VertexPositionNormalTexture((normal + side1 + side2) * tsize, normal, textureCoordinates[2])); - vertices.push_back(VertexPositionNormalTexture((normal + side1 - side2) * tsize, normal, textureCoordinates[3])); - } - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); - - if ( invertn ) - InvertNormals( vertices ); + ComputeBox(vertices, indices, size, rhcoords, invertn); } @@ -497,7 +391,7 @@ std::unique_ptr GeometricPrimitive::CreateSphere(_In_ ID3D11 { VertexCollection vertices; IndexCollection indices; - CreateSphere(vertices, indices, diameter, tessellation, rhcoords, invertn); + ComputeSphere(vertices, indices, diameter, tessellation, rhcoords, invertn); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -509,73 +403,7 @@ std::unique_ptr GeometricPrimitive::CreateSphere(_In_ ID3D11 void GeometricPrimitive::CreateSphere(std::vector& vertices, std::vector& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn) { - vertices.clear(); - indices.clear(); - - if (tessellation < 3) - throw std::out_of_range("tesselation parameter out of range"); - - size_t verticalSegments = tessellation; - size_t horizontalSegments = tessellation * 2; - - float radius = diameter / 2; - - // Create rings of vertices at progressively higher latitudes. - for (size_t i = 0; i <= verticalSegments; i++) - { - float v = 1 - (float)i / verticalSegments; - - float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; - float dy, dxz; - - XMScalarSinCos(&dy, &dxz, latitude); - - // Create a single ring of vertices at this latitude. - for (size_t j = 0; j <= horizontalSegments; j++) - { - float u = (float)j / horizontalSegments; - - float longitude = j * XM_2PI / horizontalSegments; - float dx, dz; - - XMScalarSinCos(&dx, &dz, longitude); - - dx *= dxz; - dz *= dxz; - - XMVECTOR normal = XMVectorSet(dx, dy, dz, 0); - XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); - - vertices.push_back(VertexPositionNormalTexture(normal * radius, normal, textureCoordinate)); - } - } - - // Fill the index buffer with triangles joining each pair of latitude rings. - size_t stride = horizontalSegments + 1; - - for (size_t i = 0; i < verticalSegments; i++) - { - for (size_t j = 0; j <= horizontalSegments; j++) - { - size_t nextI = i + 1; - size_t nextJ = (j + 1) % stride; - - index_push_back(indices, i * stride + j); - index_push_back(indices, nextI * stride + j); - index_push_back(indices, i * stride + nextJ); - - index_push_back(indices, i * stride + nextJ); - index_push_back(indices, nextI * stride + j); - index_push_back(indices, nextI * stride + nextJ); - } - } - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); - - if ( invertn ) - InvertNormals( vertices ); + ComputeSphere(vertices, indices, diameter, tessellation, rhcoords, invertn); } @@ -588,7 +416,7 @@ std::unique_ptr GeometricPrimitive::CreateGeoSphere(_In_ ID3 { VertexCollection vertices; IndexCollection indices; - CreateGeoSphere(vertices, indices, diameter, tessellation, rhcoords); + ComputeGeoSphere(vertices, indices, diameter, tessellation, rhcoords); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -600,319 +428,7 @@ std::unique_ptr GeometricPrimitive::CreateGeoSphere(_In_ ID3 void GeometricPrimitive::CreateGeoSphere(std::vector& vertices, std::vector& indices, float diameter, size_t tessellation, bool rhcoords) { - vertices.clear(); - indices.clear(); - - // An undirected edge between two vertices, represented by a pair of indexes into a vertex array. - // Becuse this edge is undirected, (a,b) is the same as (b,a). - typedef std::pair UndirectedEdge; - - // Makes an undirected edge. Rather than overloading comparison operators to give us the (a,b)==(b,a) property, - // we'll just ensure that the larger of the two goes first. This'll simplify things greatly. - auto makeUndirectedEdge = [](uint16_t a, uint16_t b) - { - return std::make_pair(std::max(a, b), std::min(a, b)); - }; - - // Key: an edge - // Value: the index of the vertex which lies midway between the two vertices pointed to by the key value - // This map is used to avoid duplicating vertices when subdividing triangles along edges. - typedef std::map EdgeSubdivisionMap; - - - static const XMFLOAT3 OctahedronVertices[] = - { - // when looking down the negative z-axis (into the screen) - XMFLOAT3( 0, 1, 0), // 0 top - XMFLOAT3( 0, 0, -1), // 1 front - XMFLOAT3( 1, 0, 0), // 2 right - XMFLOAT3( 0, 0, 1), // 3 back - XMFLOAT3(-1, 0, 0), // 4 left - XMFLOAT3( 0, -1, 0), // 5 bottom - }; - static const uint16_t OctahedronIndices[] = - { - 0, 1, 2, // top front-right face - 0, 2, 3, // top back-right face - 0, 3, 4, // top back-left face - 0, 4, 1, // top front-left face - 5, 1, 4, // bottom front-left face - 5, 4, 3, // bottom back-left face - 5, 3, 2, // bottom back-right face - 5, 2, 1, // bottom front-right face - }; - - const float radius = diameter / 2.0f; - - // Start with an octahedron; copy the data into the vertex/index collection. - - std::vector vertexPositions(std::begin(OctahedronVertices), std::end(OctahedronVertices)); - - indices.insert(indices.begin(), std::begin(OctahedronIndices), std::end(OctahedronIndices)); - - // We know these values by looking at the above index list for the octahedron. Despite the subdivisions that are - // about to go on, these values aren't ever going to change because the vertices don't move around in the array. - // We'll need these values later on to fix the singularities that show up at the poles. - const uint16_t northPoleIndex = 0; - const uint16_t southPoleIndex = 5; - - for (size_t iSubdivision = 0; iSubdivision < tessellation; ++iSubdivision) - { - assert(indices.size() % 3 == 0); // sanity - - // We use this to keep track of which edges have already been subdivided. - EdgeSubdivisionMap subdividedEdges; - - // The new index collection after subdivision. - IndexCollection newIndices; - - const size_t triangleCount = indices.size() / 3; - for (size_t iTriangle = 0; iTriangle < triangleCount; ++iTriangle) - { - // For each edge on this triangle, create a new vertex in the middle of that edge. - // The winding order of the triangles we output are the same as the winding order of the inputs. - - // Indices of the vertices making up this triangle - uint16_t iv0 = indices[iTriangle*3+0]; - uint16_t iv1 = indices[iTriangle*3+1]; - uint16_t iv2 = indices[iTriangle*3+2]; - - // Get the new vertices - XMFLOAT3 v01; // vertex on the midpoint of v0 and v1 - XMFLOAT3 v12; // ditto v1 and v2 - XMFLOAT3 v20; // ditto v2 and v0 - uint16_t iv01; // index of v01 - uint16_t iv12; // index of v12 - uint16_t iv20; // index of v20 - - // Function that, when given the index of two vertices, creates a new vertex at the midpoint of those vertices. - auto divideEdge = [&](uint16_t i0, uint16_t i1, XMFLOAT3& outVertex, uint16_t& outIndex) - { - const UndirectedEdge edge = makeUndirectedEdge(i0, i1); - - // Check to see if we've already generated this vertex - auto it = subdividedEdges.find(edge); - if (it != subdividedEdges.end()) - { - // We've already generated this vertex before - outIndex = it->second; // the index of this vertex - outVertex = vertexPositions[outIndex]; // and the vertex itself - } - else - { - // Haven't generated this vertex before: so add it now - - // outVertex = (vertices[i0] + vertices[i1]) / 2 - XMStoreFloat3( - &outVertex, - XMVectorScale( - XMVectorAdd(XMLoadFloat3(&vertexPositions[i0]), XMLoadFloat3(&vertexPositions[i1])), - 0.5f - ) - ); - - outIndex = static_cast( vertexPositions.size() ); - CheckIndexOverflow(outIndex); - vertexPositions.push_back(outVertex); - - // Now add it to the map. - subdividedEdges.insert(std::make_pair(edge, outIndex)); - } - }; - - // Add/get new vertices and their indices - divideEdge(iv0, iv1, v01, iv01); - divideEdge(iv1, iv2, v12, iv12); - divideEdge(iv0, iv2, v20, iv20); - - // Add the new indices. We have four new triangles from our original one: - // v0 - // o - // /a\ - // v20 o---o v01 - // /b\c/d\ - // v2 o---o---o v1 - // v12 - const uint16_t indicesToAdd[] = - { - iv0, iv01, iv20, // a - iv20, iv12, iv2, // b - iv20, iv01, iv12, // c - iv01, iv1, iv12, // d - }; - newIndices.insert(newIndices.end(), std::begin(indicesToAdd), std::end(indicesToAdd)); - } - - indices = std::move(newIndices); - } - - // Now that we've completed subdivision, fill in the final vertex collection - vertices.reserve(vertexPositions.size()); - for (auto it = vertexPositions.begin(); it != vertexPositions.end(); ++it) - { - auto vertexValue = *it; - - auto normal = XMVector3Normalize(XMLoadFloat3(&vertexValue)); - auto pos = XMVectorScale(normal, radius); - - XMFLOAT3 normalFloat3; - XMStoreFloat3(&normalFloat3, normal); - - // calculate texture coordinates for this vertex - float longitude = atan2(normalFloat3.x, -normalFloat3.z); - float latitude = acos(normalFloat3.y); - - float u = longitude / XM_2PI + 0.5f; - float v = latitude / XM_PI; - - auto texcoord = XMVectorSet(1.0f - u, v, 0.0f, 0.0f); - vertices.push_back(VertexPositionNormalTexture(pos, normal, texcoord)); - } - - // There are a couple of fixes to do. One is a texture coordinate wraparound fixup. At some point, there will be - // a set of triangles somewhere in the mesh with texture coordinates such that the wraparound across 0.0/1.0 - // occurs across that triangle. Eg. when the left hand side of the triangle has a U coordinate of 0.98 and the - // right hand side has a U coordinate of 0.0. The intent is that such a triangle should render with a U of 0.98 to - // 1.0, not 0.98 to 0.0. If we don't do this fixup, there will be a visible seam across one side of the sphere. - // - // Luckily this is relatively easy to fix. There is a straight edge which runs down the prime meridian of the - // completed sphere. If you imagine the vertices along that edge, they circumscribe a semicircular arc starting at - // y=1 and ending at y=-1, and sweeping across the range of z=0 to z=1. x stays zero. It's along this edge that we - // need to duplicate our vertices - and provide the correct texture coordinates. - size_t preFixupVertexCount = vertices.size(); - for (size_t i = 0; i < preFixupVertexCount; ++i) - { - // This vertex is on the prime meridian if position.x and texcoord.u are both zero (allowing for small epsilon). - bool isOnPrimeMeridian = XMVector2NearEqual( - XMVectorSet(vertices[i].position.x, vertices[i].textureCoordinate.x, 0.0f, 0.0f), - XMVectorZero(), - XMVectorSplatEpsilon()); - - if (isOnPrimeMeridian) - { - size_t newIndex = vertices.size(); // the index of this vertex that we're about to add - CheckIndexOverflow(newIndex); - - // copy this vertex, correct the texture coordinate, and add the vertex - VertexPositionNormalTexture v = vertices[i]; - v.textureCoordinate.x = 1.0f; - vertices.push_back(v); - - // Now find all the triangles which contain this vertex and update them if necessary - for (size_t j = 0; j < indices.size(); j += 3) - { - uint16_t* triIndex0 = &indices[j+0]; - uint16_t* triIndex1 = &indices[j+1]; - uint16_t* triIndex2 = &indices[j+2]; - - if (*triIndex0 == i) - { - // nothing; just keep going - } - else if (*triIndex1 == i) - { - std::swap(triIndex0, triIndex1); // swap the pointers (not the values) - } - else if (*triIndex2 == i) - { - std::swap(triIndex0, triIndex2); // swap the pointers (not the values) - } - else - { - // this triangle doesn't use the vertex we're interested in - continue; - } - - // If we got to this point then triIndex0 is the pointer to the index to the vertex we're looking at - assert(*triIndex0 == i); - assert(*triIndex1 != i && *triIndex2 != i); // assume no degenerate triangles - - const VertexPositionNormalTexture& v0 = vertices[*triIndex0]; - const VertexPositionNormalTexture& v1 = vertices[*triIndex1]; - const VertexPositionNormalTexture& v2 = vertices[*triIndex2]; - - // check the other two vertices to see if we might need to fix this triangle - - if (abs(v0.textureCoordinate.x - v1.textureCoordinate.x) > 0.5f || - abs(v0.textureCoordinate.x - v2.textureCoordinate.x) > 0.5f) - { - // yep; replace the specified index to point to the new, corrected vertex - *triIndex0 = static_cast(newIndex); - } - } - } - } - - // And one last fix we need to do: the poles. A common use-case of a sphere mesh is to map a rectangular texture onto - // it. If that happens, then the poles become singularities which map the entire top and bottom rows of the texture - // onto a single point. In general there's no real way to do that right. But to match the behavior of non-geodesic - // spheres, we need to duplicate the pole vertex for every triangle that uses it. This will introduce seams near the - // poles, but reduce stretching. - auto fixPole = [&](size_t poleIndex) - { - auto poleVertex = vertices[poleIndex]; - bool overwrittenPoleVertex = false; // overwriting the original pole vertex saves us one vertex - - for (size_t i = 0; i < indices.size(); i += 3) - { - // These pointers point to the three indices which make up this triangle. pPoleIndex is the pointer to the - // entry in the index array which represents the pole index, and the other two pointers point to the other - // two indices making up this triangle. - uint16_t* pPoleIndex; - uint16_t* pOtherIndex0; - uint16_t* pOtherIndex1; - if (indices[i + 0] == poleIndex) - { - pPoleIndex = &indices[i + 0]; - pOtherIndex0 = &indices[i + 1]; - pOtherIndex1 = &indices[i + 2]; - } - else if (indices[i + 1] == poleIndex) - { - pPoleIndex = &indices[i + 1]; - pOtherIndex0 = &indices[i + 2]; - pOtherIndex1 = &indices[i + 0]; - } - else if (indices[i + 2] == poleIndex) - { - pPoleIndex = &indices[i + 2]; - pOtherIndex0 = &indices[i + 0]; - pOtherIndex1 = &indices[i + 1]; - } - else - { - continue; - } - - const auto& otherVertex0 = vertices[*pOtherIndex0]; - const auto& otherVertex1 = vertices[*pOtherIndex1]; - - // Calculate the texcoords for the new pole vertex, add it to the vertices and update the index - VertexPositionNormalTexture newPoleVertex = poleVertex; - newPoleVertex.textureCoordinate.x = (otherVertex0.textureCoordinate.x + otherVertex1.textureCoordinate.x) / 2; - newPoleVertex.textureCoordinate.y = poleVertex.textureCoordinate.y; - - if (!overwrittenPoleVertex) - { - vertices[poleIndex] = newPoleVertex; - overwrittenPoleVertex = true; - } - else - { - CheckIndexOverflow(vertices.size()); - - *pPoleIndex = static_cast(vertices.size()); - vertices.push_back(newPoleVertex); - } - } - }; - - fixPole(northPoleIndex); - fixPole(southPoleIndex); - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); + ComputeGeoSphere(vertices, indices, diameter, tessellation, rhcoords); } @@ -920,80 +436,12 @@ void GeometricPrimitive::CreateGeoSphere(std::vector(circleVector), textureScale, g_XMOneHalf); - - vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); - } -} - - // Creates a cylinder primitive. std::unique_ptr GeometricPrimitive::CreateCylinder(_In_ ID3D11DeviceContext* deviceContext, float height, float diameter, size_t tessellation, bool rhcoords) { VertexCollection vertices; IndexCollection indices; - CreateCylinder(vertices, indices, height, diameter, tessellation, rhcoords); + ComputeCylinder(vertices, indices, height, diameter, tessellation, rhcoords); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1005,49 +453,7 @@ std::unique_ptr GeometricPrimitive::CreateCylinder(_In_ ID3D void GeometricPrimitive::CreateCylinder(std::vector& vertices, std::vector& indices, float height, float diameter, size_t tessellation, bool rhcoords) { - vertices.clear(); - indices.clear(); - - if (tessellation < 3) - throw std::out_of_range("tesselation parameter out of range"); - - height /= 2; - - XMVECTOR topOffset = g_XMIdentityR1 * height; - - float radius = diameter / 2; - size_t stride = tessellation + 1; - - // Create a ring of triangles around the outside of the cylinder. - for (size_t i = 0; i <= tessellation; i++) - { - XMVECTOR normal = GetCircleVector(i, tessellation); - - XMVECTOR sideOffset = normal * radius; - - float u = (float)i / tessellation; - - XMVECTOR textureCoordinate = XMLoadFloat(&u); - - vertices.push_back(VertexPositionNormalTexture(sideOffset + topOffset, normal, textureCoordinate)); - vertices.push_back(VertexPositionNormalTexture(sideOffset - topOffset, normal, textureCoordinate + g_XMIdentityR1)); - - index_push_back(indices, i * 2); - index_push_back(indices, (i * 2 + 2) % (stride * 2)); - index_push_back(indices, i * 2 + 1); - - index_push_back(indices, i * 2 + 1); - index_push_back(indices, (i * 2 + 2) % (stride * 2)); - index_push_back(indices, (i * 2 + 3) % (stride * 2)); - } - - // Create flat triangle fan caps to seal the top and bottom. - CreateCylinderCap(vertices, indices, tessellation, height, radius, true); - CreateCylinderCap(vertices, indices, tessellation, height, radius, false); - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); + ComputeCylinder(vertices, indices, height, diameter, tessellation, rhcoords); } @@ -1056,7 +462,7 @@ std::unique_ptr GeometricPrimitive::CreateCone(_In_ ID3D11De { VertexCollection vertices; IndexCollection indices; - CreateCone(vertices, indices, diameter, height, tessellation, rhcoords); + ComputeCone(vertices, indices, diameter, height, tessellation, rhcoords); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1068,50 +474,7 @@ std::unique_ptr GeometricPrimitive::CreateCone(_In_ ID3D11De void GeometricPrimitive::CreateCone(std::vector& vertices, std::vector& indices, float diameter, float height, size_t tessellation, bool rhcoords) { - vertices.clear(); - indices.clear(); - - if (tessellation < 3) - throw std::out_of_range("tesselation parameter out of range"); - - height /= 2; - - XMVECTOR topOffset = g_XMIdentityR1 * height; - - float radius = diameter / 2; - size_t stride = tessellation + 1; - - // Create a ring of triangles around the outside of the cone. - for (size_t i = 0; i <= tessellation; i++) - { - XMVECTOR circlevec = GetCircleVector(i, tessellation); - - XMVECTOR sideOffset = circlevec * radius; - - float u = (float)i / tessellation; - - XMVECTOR textureCoordinate = XMLoadFloat(&u); - - XMVECTOR pt = sideOffset - topOffset; - - XMVECTOR normal = XMVector3Cross( GetCircleTangent( i, tessellation ), topOffset - pt ); - normal = XMVector3Normalize( normal ); - - // Duplicate the top vertex for distinct normals - vertices.push_back(VertexPositionNormalTexture(topOffset, normal, g_XMZero)); - vertices.push_back(VertexPositionNormalTexture(pt, normal, textureCoordinate + g_XMIdentityR1 )); - - index_push_back(indices, i * 2); - index_push_back(indices, (i * 2 + 3) % (stride * 2)); - index_push_back(indices, (i * 2 + 1) % (stride * 2)); - } - - // Create flat triangle fan caps to seal the bottom. - CreateCylinderCap(vertices, indices, tessellation, height, radius, false); - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); + ComputeCone(vertices, indices, diameter, height, tessellation, rhcoords); } @@ -1124,7 +487,7 @@ std::unique_ptr GeometricPrimitive::CreateTorus(_In_ ID3D11D { VertexCollection vertices; IndexCollection indices; - CreateTorus( vertices, indices, diameter, thickness, tessellation, rhcoords ); + ComputeTorus( vertices, indices, diameter, thickness, tessellation, rhcoords ); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1136,62 +499,7 @@ std::unique_ptr GeometricPrimitive::CreateTorus(_In_ ID3D11D void GeometricPrimitive::CreateTorus(std::vector& vertices, std::vector& indices, float diameter, float thickness, size_t tessellation, bool rhcoords) { - vertices.clear(); - indices.clear(); - - if (tessellation < 3) - throw std::out_of_range("tesselation parameter out of range"); - - size_t stride = tessellation + 1; - - // First we loop around the main ring of the torus. - for (size_t i = 0; i <= tessellation; i++) - { - float u = (float)i / tessellation; - - float outerAngle = i * XM_2PI / tessellation - XM_PIDIV2; - - // Create a transform matrix that will align geometry to - // slice perpendicularly though the current ring position. - XMMATRIX transform = XMMatrixTranslation(diameter / 2, 0, 0) * XMMatrixRotationY(outerAngle); - - // Now we loop along the other axis, around the side of the tube. - for (size_t j = 0; j <= tessellation; j++) - { - float v = 1 - (float)j / tessellation; - - float innerAngle = j * XM_2PI / tessellation + XM_PI; - float dx, dy; - - XMScalarSinCos(&dy, &dx, innerAngle); - - // Create a vertex. - XMVECTOR normal = XMVectorSet(dx, dy, 0, 0); - XMVECTOR position = normal * thickness / 2; - XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); - - position = XMVector3Transform(position, transform); - normal = XMVector3TransformNormal(normal, transform); - - vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); - - // And create indices for two triangles. - size_t nextI = (i + 1) % stride; - size_t nextJ = (j + 1) % stride; - - index_push_back(indices, i * stride + j); - index_push_back(indices, i * stride + nextJ); - index_push_back(indices, nextI * stride + j); - - index_push_back(indices, i * stride + nextJ); - index_push_back(indices, nextI * stride + nextJ); - index_push_back(indices, nextI * stride + j); - } - } - - // Build RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); + ComputeTorus(vertices, indices, diameter, thickness, tessellation, rhcoords); } @@ -1203,7 +511,7 @@ std::unique_ptr GeometricPrimitive::CreateTetrahedron(_In_ I { VertexCollection vertices; IndexCollection indices; - CreateTetrahedron(vertices, indices, size, rhcoords); + ComputeTetrahedron(vertices, indices, size, rhcoords); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1215,57 +523,7 @@ std::unique_ptr GeometricPrimitive::CreateTetrahedron(_In_ I void GeometricPrimitive::CreateTetrahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords) { - vertices.clear(); - indices.clear(); - - static const XMVECTORF32 verts[4] = - { - { 0.f, 0.f, 1.f }, - { 2.f*SQRT2/3.f, 0.f, -1.f/3.f }, - { -SQRT2/3.f, SQRT6/3.f, -1.f/3.f }, - { -SQRT2/3.f, -SQRT6/3.f, -1.f/3.f } - }; - - static const uint32_t faces[4*3] = - { - 0, 1, 2, - 0, 2, 3, - 0, 3, 1, - 1, 3, 2, - }; - - for( size_t j = 0; j < _countof(faces); j += 3 ) - { - uint32_t v0 = faces[ j ]; - uint32_t v1 = faces[ j + 1 ]; - uint32_t v2 = faces[ j + 2 ]; - - XMVECTOR normal = XMVector3Cross( verts[ v1 ].v - verts[ v0 ].v, - verts[ v2 ].v - verts[ v0 ].v ); - normal = XMVector3Normalize( normal ); - - size_t base = vertices.size(); - index_push_back(indices, base ); - index_push_back(indices, base + 1 ); - index_push_back(indices, base + 2 ); - - // Duplicate vertices to use face normals - XMVECTOR position = XMVectorScale( verts[ v0 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMZero /* 0, 0 */ ) ); - - position = XMVectorScale( verts[ v1 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR0 /* 1, 0 */ ) ); - - position = XMVectorScale( verts[ v2 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR1 /* 0, 1 */ ) ); - } - - // Built LH above - if ( rhcoords ) - ReverseWinding( indices, vertices ); - - assert( vertices.size() == 4*3 ); - assert( indices.size() == 4*3 ); + ComputeTetrahedron(vertices, indices, size, rhcoords); } @@ -1276,7 +534,7 @@ std::unique_ptr GeometricPrimitive::CreateOctahedron(_In_ ID { VertexCollection vertices; IndexCollection indices; - CreateOctahedron(vertices, indices, size, rhcoords ); + ComputeOctahedron(vertices, indices, size, rhcoords ); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1288,63 +546,7 @@ std::unique_ptr GeometricPrimitive::CreateOctahedron(_In_ ID void GeometricPrimitive::CreateOctahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords ) { - vertices.clear(); - indices.clear(); - - static const XMVECTORF32 verts[6] = - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 1, 0 }, - { 0, -1, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 } - }; - - static const uint32_t faces[8*3] = - { - 4, 0, 2, - 4, 2, 1, - 4, 1, 3, - 4, 3, 0, - 5, 2, 0, - 5, 1, 2, - 5, 3, 1, - 5, 0, 3 - }; - - for( size_t j = 0; j < _countof(faces); j += 3 ) - { - uint32_t v0 = faces[ j ]; - uint32_t v1 = faces[ j + 1 ]; - uint32_t v2 = faces[ j + 2 ]; - - XMVECTOR normal = XMVector3Cross( verts[ v1 ].v - verts[ v0 ].v, - verts[ v2 ].v - verts[ v0 ].v ); - normal = XMVector3Normalize( normal ); - - size_t base = vertices.size(); - index_push_back(indices, base ); - index_push_back(indices, base + 1 ); - index_push_back(indices, base + 2 ); - - // Duplicate vertices to use face normals - XMVECTOR position = XMVectorScale( verts[ v0 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMZero /* 0, 0 */ ) ); - - position = XMVectorScale( verts[ v1 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR0 /* 1, 0 */ ) ); - - position = XMVectorScale( verts[ v2 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR1 /* 0, 1*/ ) ); - } - - // Built LH above - if ( rhcoords ) - ReverseWinding( indices, vertices ); - - assert( vertices.size() == 8*3 ); - assert( indices.size() == 8*3 ); + ComputeOctahedron(vertices, indices, size, rhcoords); } @@ -1356,7 +558,7 @@ std::unique_ptr GeometricPrimitive::CreateDodecahedron(_In_ { VertexCollection vertices; IndexCollection indices; - CreateDodecahedron( vertices, indices, size, rhcoords ); + ComputeDodecahedron( vertices, indices, size, rhcoords ); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1368,128 +570,7 @@ std::unique_ptr GeometricPrimitive::CreateDodecahedron(_In_ void GeometricPrimitive::CreateDodecahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords ) { - vertices.clear(); - indices.clear(); - - static const float a = 1.f/SQRT3; - static const float b = 0.356822089773089931942f; // sqrt( ( 3 - sqrt(5) ) / 6 ) - static const float c = 0.934172358962715696451f; // sqrt( ( 3 + sqrt(5) ) / 6 ); - - static const XMVECTORF32 verts[20] = - { - { a, a, a }, - { a, a, -a }, - { a, -a, a }, - { a, -a, -a }, - { -a, a, a }, - { -a, a, -a }, - { -a, -a, a }, - { -a, -a, -a }, - { b, c, 0 }, - { -b, c, 0 }, - { b, -c, 0 }, - { -b, -c, 0 }, - { c, 0, b }, - { c, 0, -b }, - { -c, 0, b }, - { -c, 0, -b }, - { 0, b, c }, - { 0, -b, c }, - { 0, b, -c }, - { 0, -b, -c } - }; - - static const uint32_t faces[12*5] = - { - 0, 8, 9, 4, 16, - 0, 16, 17, 2, 12, - 12, 2, 10, 3, 13, - 9, 5, 15, 14, 4, - 3, 19, 18, 1, 13, - 7, 11, 6, 14, 15, - 0, 12, 13, 1, 8, - 8, 1, 18, 5, 9, - 16, 4, 14, 6, 17, - 6, 11, 10, 2, 17, - 7, 15, 5, 18, 19, - 7, 19, 3, 10, 11, - }; - - static const XMVECTORF32 textureCoordinates[5] = - { - { 0.654508f, 0.0244717f }, - { 0.0954915f, 0.206107f }, - { 0.0954915f, 0.793893f }, - { 0.654508f, 0.975528f }, - { 1.f, 0.5f } - }; - - static const uint32_t textureIndex[12][5] = - { - { 0, 1, 2, 3, 4 }, - { 2, 3, 4, 0, 1 }, - { 4, 0, 1, 2, 3 }, - { 1, 2, 3, 4, 0 }, - { 2, 3, 4, 0, 1 }, - { 0, 1, 2, 3, 4 }, - { 1, 2, 3, 4, 0 }, - { 4, 0, 1, 2, 3 }, - { 4, 0, 1, 2, 3 }, - { 1, 2, 3, 4, 0 }, - { 0, 1, 2, 3, 4 }, - { 2, 3, 4, 0, 1 }, - }; - - size_t t = 0; - for( size_t j = 0; j < _countof(faces); j += 5, ++t ) - { - uint32_t v0 = faces[ j ]; - uint32_t v1 = faces[ j + 1 ]; - uint32_t v2 = faces[ j + 2 ]; - uint32_t v3 = faces[ j + 3 ]; - uint32_t v4 = faces[ j + 4 ]; - - XMVECTOR normal = XMVector3Cross( verts[ v1 ].v - verts[ v0 ].v, - verts[ v2 ].v - verts[ v0 ].v ); - normal = XMVector3Normalize( normal ); - - size_t base = vertices.size(); - - index_push_back(indices, base ); - index_push_back(indices, base + 1 ); - index_push_back(indices, base + 2 ); - - index_push_back(indices, base ); - index_push_back(indices, base + 2 ); - index_push_back(indices, base + 3 ); - - index_push_back(indices, base ); - index_push_back(indices, base + 3 ); - index_push_back(indices, base + 4 ); - - // Duplicate vertices to use face normals - XMVECTOR position = XMVectorScale( verts[ v0 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, textureCoordinates[ textureIndex[t][0] ] ) ); - - position = XMVectorScale( verts[ v1 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, textureCoordinates[ textureIndex[t][1] ] ) ); - - position = XMVectorScale( verts[ v2 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, textureCoordinates[ textureIndex[t][2] ] ) ); - - position = XMVectorScale( verts[ v3 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, textureCoordinates[ textureIndex[t][3] ] ) ); - - position = XMVectorScale( verts[ v4 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, textureCoordinates[ textureIndex[t][4] ] ) ); - } - - // Built LH above - if ( rhcoords ) - ReverseWinding( indices, vertices ); - - assert( vertices.size() == 12*5 ); - assert( indices.size() == 12*3*3 ); + ComputeDodecahedron(vertices, indices, size, rhcoords); } @@ -1501,7 +582,7 @@ std::unique_ptr GeometricPrimitive::CreateIcosahedron(_In_ I { VertexCollection vertices; IndexCollection indices; - CreateIcosahedron( vertices, indices, size, rhcoords ); + ComputeIcosahedron( vertices, indices, size, rhcoords ); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1513,84 +594,7 @@ std::unique_ptr GeometricPrimitive::CreateIcosahedron(_In_ I void GeometricPrimitive::CreateIcosahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords ) { - vertices.clear(); - indices.clear(); - - static const float t = 1.618033988749894848205f; // (1 + sqrt(5)) / 2 - static const float t2 = 1.519544995837552493271f; // sqrt( 1 + sqr( (1 + sqrt(5)) / 2 ) ) - - static const XMVECTORF32 verts[12] = - { - { t/t2, 1.f/t2, 0 }, - { -t/t2, 1.f/t2, 0 }, - { t/t2, -1.f/t2, 0 }, - { -t/t2, -1.f/t2, 0 }, - { 1.f/t2, 0, t/t2 }, - { 1.f/t2, 0, -t/t2 }, - { -1.f/t2, 0, t/t2 }, - { -1.f/t2, 0, -t/t2 }, - { 0, t/t2, 1.f/t2 }, - { 0, -t/t2, 1.f/t2 }, - { 0, t/t2, -1.f/t2 }, - { 0, -t/t2, -1.f/t2 } - }; - - static const uint32_t faces[20*3] = - { - 0, 8, 4, - 0, 5, 10, - 2, 4, 9, - 2, 11, 5, - 1, 6, 8, - 1, 10, 7, - 3, 9, 6, - 3, 7, 11, - 0, 10, 8, - 1, 8, 10, - 2, 9, 11, - 3, 11, 9, - 4, 2, 0, - 5, 0, 2, - 6, 1, 3, - 7, 3, 1, - 8, 6, 4, - 9, 4, 6, - 10, 5, 7, - 11, 7, 5 - }; - - for( size_t j = 0; j < _countof(faces); j += 3 ) - { - uint32_t v0 = faces[ j ]; - uint32_t v1 = faces[ j + 1 ]; - uint32_t v2 = faces[ j + 2 ]; - - XMVECTOR normal = XMVector3Cross( verts[ v1 ].v - verts[ v0 ].v, - verts[ v2 ].v - verts[ v0 ].v ); - normal = XMVector3Normalize( normal ); - - size_t base = vertices.size(); - index_push_back(indices, base ); - index_push_back(indices, base + 1 ); - index_push_back(indices, base + 2 ); - - // Duplicate vertices to use face normals - XMVECTOR position = XMVectorScale( verts[ v0 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMZero /* 0, 0 */ ) ); - - position = XMVectorScale( verts[ v1 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR0 /* 1, 0 */ ) ); - - position = XMVectorScale( verts[ v2 ], size ); - vertices.push_back( VertexPositionNormalTexture( position, normal, g_XMIdentityR1 /* 0, 1 */ ) ); - } - - // Built LH above - if ( rhcoords ) - ReverseWinding( indices, vertices ); - - assert( vertices.size() == 20*3 ); - assert( indices.size() == 20*3 ); + ComputeIcosahedron(vertices, indices, size, rhcoords); } @@ -1598,45 +602,12 @@ void GeometricPrimitive::CreateIcosahedron(std::vector GeometricPrimitive::CreateTeapot(_In_ ID3D11DeviceContext* deviceContext, float size, size_t tessellation, bool rhcoords) { VertexCollection vertices; IndexCollection indices; - CreateTeapot(vertices, indices, size, tessellation, rhcoords); + ComputeTeapot(vertices, indices, size, tessellation, rhcoords); // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); @@ -1648,40 +619,7 @@ std::unique_ptr GeometricPrimitive::CreateTeapot(_In_ ID3D11 void GeometricPrimitive::CreateTeapot(std::vector& vertices, std::vector& indices, float size, size_t tessellation, bool rhcoords) { - vertices.clear(); - indices.clear(); - - if (tessellation < 1) - throw std::out_of_range("tesselation parameter out of range"); - - XMVECTOR scaleVector = XMVectorReplicate(size); - - XMVECTOR scaleNegateX = scaleVector * g_XMNegateX; - XMVECTOR scaleNegateZ = scaleVector * g_XMNegateZ; - XMVECTOR scaleNegateXZ = scaleVector * g_XMNegateX * g_XMNegateZ; - - for (int i = 0; i < sizeof(TeapotPatches) / sizeof(TeapotPatches[0]); i++) - { - TeapotPatch const& patch = TeapotPatches[i]; - - // Because the teapot is symmetrical from left to right, we only store - // data for one side, then tessellate each patch twice, mirroring in X. - TessellatePatch(vertices, indices, patch, tessellation, scaleVector, false); - TessellatePatch(vertices, indices, patch, tessellation, scaleNegateX, true); - - if (patch.mirrorZ) - { - // Some parts of the teapot (the body, lid, and rim, but not the - // handle or spout) are also symmetrical from front to back, so - // we tessellate them four times, mirroring in Z as well as X. - TessellatePatch(vertices, indices, patch, tessellation, scaleNegateZ, true); - TessellatePatch(vertices, indices, patch, tessellation, scaleNegateXZ, false); - } - } - - // Built RH above - if ( !rhcoords ) - ReverseWinding( indices, vertices ); + ComputeTeapot(vertices, indices, size, tessellation, rhcoords); } @@ -1692,19 +630,19 @@ void GeometricPrimitive::CreateTeapot(std::vector& std::unique_ptr GeometricPrimitive::CreateCustom(_In_ ID3D11DeviceContext* deviceContext, const std::vector& vertices, const std::vector& indices) { // Extra validation - if ( vertices.empty() || indices.empty() ) + if (vertices.empty() || indices.empty()) throw std::exception("Requires both vertices and indices"); - if ( indices.size() % 3 ) + if (indices.size() % 3) throw std::exception("Expected triangular faces"); size_t nVerts = vertices.size(); - if ( nVerts >= USHRT_MAX ) + if (nVerts >= USHRT_MAX) throw std::exception("Too many vertices for 16-bit index buffer"); - for( auto it = indices.cbegin(); it != indices.cend(); ++it ) + for (auto it = indices.cbegin(); it != indices.cend(); ++it) { - if ( *it >= nVerts ) + if (*it >= nVerts) { throw std::exception("Index not in vertices list"); } @@ -1712,7 +650,7 @@ std::unique_ptr GeometricPrimitive::CreateCustom(_In_ ID3D11 // Create the primitive object. std::unique_ptr primitive(new GeometricPrimitive()); - + primitive->pImpl->Initialize(deviceContext, vertices, indices); return primitive; diff --git a/Kits/DirectXTK/Src/Geometry.cpp b/Kits/DirectXTK/Src/Geometry.cpp new file mode 100644 index 00000000..6b5c3b80 --- /dev/null +++ b/Kits/DirectXTK/Src/Geometry.cpp @@ -0,0 +1,1184 @@ +//-------------------------------------------------------------------------------------- +// File: Geometry.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Geometry.h" +#include "Bezier.h" + +using namespace DirectX; + +namespace +{ + const float SQRT2 = 1.41421356237309504880f; + const float SQRT3 = 1.73205080756887729352f; + const float SQRT6 = 2.44948974278317809820f; + + inline void CheckIndexOverflow(size_t value) + { + // Use >=, not > comparison, because some D3D level 9_x hardware does not support 0xFFFF index values. + if (value >= USHRT_MAX) + throw std::exception("Index value out of range: cannot tesselate primitive so finely"); + } + + + // Collection types used when generating the geometry. + inline void index_push_back(IndexCollection& indices, size_t value) + { + CheckIndexOverflow(value); + indices.push_back((uint16_t)value); + } + + + // Helper for flipping winding of geometric primitives for LH vs. RH coords + inline void ReverseWinding(IndexCollection& indices, VertexCollection& vertices) + { + assert((indices.size() % 3) == 0); + for (auto it = indices.begin(); it != indices.end(); it += 3) + { + std::swap(*it, *(it + 2)); + } + + for (auto it = vertices.begin(); it != vertices.end(); ++it) + { + it->textureCoordinate.x = (1.f - it->textureCoordinate.x); + } + } + + + // Helper for inverting normals of geometric primitives for 'inside' vs. 'outside' viewing + inline void InvertNormals(VertexCollection& vertices) + { + for (auto it = vertices.begin(); it != vertices.end(); ++it) + { + it->normal.x = -it->normal.x; + it->normal.y = -it->normal.y; + it->normal.z = -it->normal.z; + } + } +} + + +//-------------------------------------------------------------------------------------- +// Cube (aka a Hexahedron) or Box +//-------------------------------------------------------------------------------------- +void DirectX::ComputeBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords, bool invertn) +{ + vertices.clear(); + indices.clear(); + + // A box has six faces, each one pointing in a different direction. + const int FaceCount = 6; + + static const XMVECTORF32 faceNormals[FaceCount] = + { + { 0, 0, 1 }, + { 0, 0, -1 }, + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + }; + + static const XMVECTORF32 textureCoordinates[4] = + { + { 1, 0 }, + { 1, 1 }, + { 0, 1 }, + { 0, 0 }, + }; + + XMVECTOR tsize = XMLoadFloat3(&size); + tsize = XMVectorDivide(tsize, g_XMTwo); + + // Create each face in turn. + for (int i = 0; i < FaceCount; i++) + { + XMVECTOR normal = faceNormals[i]; + + // Get two vectors perpendicular both to the face normal and to each other. + XMVECTOR basis = (i >= 4) ? g_XMIdentityR2 : g_XMIdentityR1; + + XMVECTOR side1 = XMVector3Cross(normal, basis); + XMVECTOR side2 = XMVector3Cross(normal, side1); + + // Six indices (two triangles) per face. + size_t vbase = vertices.size(); + index_push_back(indices, vbase + 0); + index_push_back(indices, vbase + 1); + index_push_back(indices, vbase + 2); + + index_push_back(indices, vbase + 0); + index_push_back(indices, vbase + 2); + index_push_back(indices, vbase + 3); + + // Four vertices per face. + vertices.push_back(VertexPositionNormalTexture((normal - side1 - side2) * tsize, normal, textureCoordinates[0])); + vertices.push_back(VertexPositionNormalTexture((normal - side1 + side2) * tsize, normal, textureCoordinates[1])); + vertices.push_back(VertexPositionNormalTexture((normal + side1 + side2) * tsize, normal, textureCoordinates[2])); + vertices.push_back(VertexPositionNormalTexture((normal + side1 - side2) * tsize, normal, textureCoordinates[3])); + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); + + if (invertn) + InvertNormals(vertices); +} + + +//-------------------------------------------------------------------------------------- +// Sphere +//-------------------------------------------------------------------------------------- +void DirectX::ComputeSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + size_t verticalSegments = tessellation; + size_t horizontalSegments = tessellation * 2; + + float radius = diameter / 2; + + // Create rings of vertices at progressively higher latitudes. + for (size_t i = 0; i <= verticalSegments; i++) + { + float v = 1 - (float)i / verticalSegments; + + float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; + float dy, dxz; + + XMScalarSinCos(&dy, &dxz, latitude); + + // Create a single ring of vertices at this latitude. + for (size_t j = 0; j <= horizontalSegments; j++) + { + float u = (float)j / horizontalSegments; + + float longitude = j * XM_2PI / horizontalSegments; + float dx, dz; + + XMScalarSinCos(&dx, &dz, longitude); + + dx *= dxz; + dz *= dxz; + + XMVECTOR normal = XMVectorSet(dx, dy, dz, 0); + XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); + + vertices.push_back(VertexPositionNormalTexture(normal * radius, normal, textureCoordinate)); + } + } + + // Fill the index buffer with triangles joining each pair of latitude rings. + size_t stride = horizontalSegments + 1; + + for (size_t i = 0; i < verticalSegments; i++) + { + for (size_t j = 0; j <= horizontalSegments; j++) + { + size_t nextI = i + 1; + size_t nextJ = (j + 1) % stride; + + index_push_back(indices, i * stride + j); + index_push_back(indices, nextI * stride + j); + index_push_back(indices, i * stride + nextJ); + + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + j); + index_push_back(indices, nextI * stride + nextJ); + } + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); + + if (invertn) + InvertNormals(vertices); +} + + +//-------------------------------------------------------------------------------------- +// Geodesic sphere +//-------------------------------------------------------------------------------------- +void DirectX::ComputeGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + // An undirected edge between two vertices, represented by a pair of indexes into a vertex array. + // Becuse this edge is undirected, (a,b) is the same as (b,a). + typedef std::pair UndirectedEdge; + + // Makes an undirected edge. Rather than overloading comparison operators to give us the (a,b)==(b,a) property, + // we'll just ensure that the larger of the two goes first. This'll simplify things greatly. + auto makeUndirectedEdge = [](uint16_t a, uint16_t b) + { + return std::make_pair(std::max(a, b), std::min(a, b)); + }; + + // Key: an edge + // Value: the index of the vertex which lies midway between the two vertices pointed to by the key value + // This map is used to avoid duplicating vertices when subdividing triangles along edges. + typedef std::map EdgeSubdivisionMap; + + + static const XMFLOAT3 OctahedronVertices[] = + { + // when looking down the negative z-axis (into the screen) + XMFLOAT3(0, 1, 0), // 0 top + XMFLOAT3(0, 0, -1), // 1 front + XMFLOAT3(1, 0, 0), // 2 right + XMFLOAT3(0, 0, 1), // 3 back + XMFLOAT3(-1, 0, 0), // 4 left + XMFLOAT3(0, -1, 0), // 5 bottom + }; + static const uint16_t OctahedronIndices[] = + { + 0, 1, 2, // top front-right face + 0, 2, 3, // top back-right face + 0, 3, 4, // top back-left face + 0, 4, 1, // top front-left face + 5, 1, 4, // bottom front-left face + 5, 4, 3, // bottom back-left face + 5, 3, 2, // bottom back-right face + 5, 2, 1, // bottom front-right face + }; + + const float radius = diameter / 2.0f; + + // Start with an octahedron; copy the data into the vertex/index collection. + + std::vector vertexPositions(std::begin(OctahedronVertices), std::end(OctahedronVertices)); + + indices.insert(indices.begin(), std::begin(OctahedronIndices), std::end(OctahedronIndices)); + + // We know these values by looking at the above index list for the octahedron. Despite the subdivisions that are + // about to go on, these values aren't ever going to change because the vertices don't move around in the array. + // We'll need these values later on to fix the singularities that show up at the poles. + const uint16_t northPoleIndex = 0; + const uint16_t southPoleIndex = 5; + + for (size_t iSubdivision = 0; iSubdivision < tessellation; ++iSubdivision) + { + assert(indices.size() % 3 == 0); // sanity + + // We use this to keep track of which edges have already been subdivided. + EdgeSubdivisionMap subdividedEdges; + + // The new index collection after subdivision. + IndexCollection newIndices; + + const size_t triangleCount = indices.size() / 3; + for (size_t iTriangle = 0; iTriangle < triangleCount; ++iTriangle) + { + // For each edge on this triangle, create a new vertex in the middle of that edge. + // The winding order of the triangles we output are the same as the winding order of the inputs. + + // Indices of the vertices making up this triangle + uint16_t iv0 = indices[iTriangle * 3 + 0]; + uint16_t iv1 = indices[iTriangle * 3 + 1]; + uint16_t iv2 = indices[iTriangle * 3 + 2]; + + // Get the new vertices + XMFLOAT3 v01; // vertex on the midpoint of v0 and v1 + XMFLOAT3 v12; // ditto v1 and v2 + XMFLOAT3 v20; // ditto v2 and v0 + uint16_t iv01; // index of v01 + uint16_t iv12; // index of v12 + uint16_t iv20; // index of v20 + + // Function that, when given the index of two vertices, creates a new vertex at the midpoint of those vertices. + auto divideEdge = [&](uint16_t i0, uint16_t i1, XMFLOAT3& outVertex, uint16_t& outIndex) + { + const UndirectedEdge edge = makeUndirectedEdge(i0, i1); + + // Check to see if we've already generated this vertex + auto it = subdividedEdges.find(edge); + if (it != subdividedEdges.end()) + { + // We've already generated this vertex before + outIndex = it->second; // the index of this vertex + outVertex = vertexPositions[outIndex]; // and the vertex itself + } + else + { + // Haven't generated this vertex before: so add it now + + // outVertex = (vertices[i0] + vertices[i1]) / 2 + XMStoreFloat3( + &outVertex, + XMVectorScale( + XMVectorAdd(XMLoadFloat3(&vertexPositions[i0]), XMLoadFloat3(&vertexPositions[i1])), + 0.5f + ) + ); + + outIndex = static_cast(vertexPositions.size()); + CheckIndexOverflow(outIndex); + vertexPositions.push_back(outVertex); + + // Now add it to the map. + subdividedEdges.insert(std::make_pair(edge, outIndex)); + } + }; + + // Add/get new vertices and their indices + divideEdge(iv0, iv1, v01, iv01); + divideEdge(iv1, iv2, v12, iv12); + divideEdge(iv0, iv2, v20, iv20); + + // Add the new indices. We have four new triangles from our original one: + // v0 + // o + // /a\ + // v20 o---o v01 + // /b\c/d\ + // v2 o---o---o v1 + // v12 + const uint16_t indicesToAdd[] = + { + iv0, iv01, iv20, // a + iv20, iv12, iv2, // b + iv20, iv01, iv12, // c + iv01, iv1, iv12, // d + }; + newIndices.insert(newIndices.end(), std::begin(indicesToAdd), std::end(indicesToAdd)); + } + + indices = std::move(newIndices); + } + + // Now that we've completed subdivision, fill in the final vertex collection + vertices.reserve(vertexPositions.size()); + for (auto it = vertexPositions.begin(); it != vertexPositions.end(); ++it) + { + auto vertexValue = *it; + + auto normal = XMVector3Normalize(XMLoadFloat3(&vertexValue)); + auto pos = XMVectorScale(normal, radius); + + XMFLOAT3 normalFloat3; + XMStoreFloat3(&normalFloat3, normal); + + // calculate texture coordinates for this vertex + float longitude = atan2(normalFloat3.x, -normalFloat3.z); + float latitude = acos(normalFloat3.y); + + float u = longitude / XM_2PI + 0.5f; + float v = latitude / XM_PI; + + auto texcoord = XMVectorSet(1.0f - u, v, 0.0f, 0.0f); + vertices.push_back(VertexPositionNormalTexture(pos, normal, texcoord)); + } + + // There are a couple of fixes to do. One is a texture coordinate wraparound fixup. At some point, there will be + // a set of triangles somewhere in the mesh with texture coordinates such that the wraparound across 0.0/1.0 + // occurs across that triangle. Eg. when the left hand side of the triangle has a U coordinate of 0.98 and the + // right hand side has a U coordinate of 0.0. The intent is that such a triangle should render with a U of 0.98 to + // 1.0, not 0.98 to 0.0. If we don't do this fixup, there will be a visible seam across one side of the sphere. + // + // Luckily this is relatively easy to fix. There is a straight edge which runs down the prime meridian of the + // completed sphere. If you imagine the vertices along that edge, they circumscribe a semicircular arc starting at + // y=1 and ending at y=-1, and sweeping across the range of z=0 to z=1. x stays zero. It's along this edge that we + // need to duplicate our vertices - and provide the correct texture coordinates. + size_t preFixupVertexCount = vertices.size(); + for (size_t i = 0; i < preFixupVertexCount; ++i) + { + // This vertex is on the prime meridian if position.x and texcoord.u are both zero (allowing for small epsilon). + bool isOnPrimeMeridian = XMVector2NearEqual( + XMVectorSet(vertices[i].position.x, vertices[i].textureCoordinate.x, 0.0f, 0.0f), + XMVectorZero(), + XMVectorSplatEpsilon()); + + if (isOnPrimeMeridian) + { + size_t newIndex = vertices.size(); // the index of this vertex that we're about to add + CheckIndexOverflow(newIndex); + + // copy this vertex, correct the texture coordinate, and add the vertex + VertexPositionNormalTexture v = vertices[i]; + v.textureCoordinate.x = 1.0f; + vertices.push_back(v); + + // Now find all the triangles which contain this vertex and update them if necessary + for (size_t j = 0; j < indices.size(); j += 3) + { + uint16_t* triIndex0 = &indices[j + 0]; + uint16_t* triIndex1 = &indices[j + 1]; + uint16_t* triIndex2 = &indices[j + 2]; + + if (*triIndex0 == i) + { + // nothing; just keep going + } + else if (*triIndex1 == i) + { + std::swap(triIndex0, triIndex1); // swap the pointers (not the values) + } + else if (*triIndex2 == i) + { + std::swap(triIndex0, triIndex2); // swap the pointers (not the values) + } + else + { + // this triangle doesn't use the vertex we're interested in + continue; + } + + // If we got to this point then triIndex0 is the pointer to the index to the vertex we're looking at + assert(*triIndex0 == i); + assert(*triIndex1 != i && *triIndex2 != i); // assume no degenerate triangles + + const VertexPositionNormalTexture& v0 = vertices[*triIndex0]; + const VertexPositionNormalTexture& v1 = vertices[*triIndex1]; + const VertexPositionNormalTexture& v2 = vertices[*triIndex2]; + + // check the other two vertices to see if we might need to fix this triangle + + if (abs(v0.textureCoordinate.x - v1.textureCoordinate.x) > 0.5f || + abs(v0.textureCoordinate.x - v2.textureCoordinate.x) > 0.5f) + { + // yep; replace the specified index to point to the new, corrected vertex + *triIndex0 = static_cast(newIndex); + } + } + } + } + + // And one last fix we need to do: the poles. A common use-case of a sphere mesh is to map a rectangular texture onto + // it. If that happens, then the poles become singularities which map the entire top and bottom rows of the texture + // onto a single point. In general there's no real way to do that right. But to match the behavior of non-geodesic + // spheres, we need to duplicate the pole vertex for every triangle that uses it. This will introduce seams near the + // poles, but reduce stretching. + auto fixPole = [&](size_t poleIndex) + { + auto poleVertex = vertices[poleIndex]; + bool overwrittenPoleVertex = false; // overwriting the original pole vertex saves us one vertex + + for (size_t i = 0; i < indices.size(); i += 3) + { + // These pointers point to the three indices which make up this triangle. pPoleIndex is the pointer to the + // entry in the index array which represents the pole index, and the other two pointers point to the other + // two indices making up this triangle. + uint16_t* pPoleIndex; + uint16_t* pOtherIndex0; + uint16_t* pOtherIndex1; + if (indices[i + 0] == poleIndex) + { + pPoleIndex = &indices[i + 0]; + pOtherIndex0 = &indices[i + 1]; + pOtherIndex1 = &indices[i + 2]; + } + else if (indices[i + 1] == poleIndex) + { + pPoleIndex = &indices[i + 1]; + pOtherIndex0 = &indices[i + 2]; + pOtherIndex1 = &indices[i + 0]; + } + else if (indices[i + 2] == poleIndex) + { + pPoleIndex = &indices[i + 2]; + pOtherIndex0 = &indices[i + 0]; + pOtherIndex1 = &indices[i + 1]; + } + else + { + continue; + } + + const auto& otherVertex0 = vertices[*pOtherIndex0]; + const auto& otherVertex1 = vertices[*pOtherIndex1]; + + // Calculate the texcoords for the new pole vertex, add it to the vertices and update the index + VertexPositionNormalTexture newPoleVertex = poleVertex; + newPoleVertex.textureCoordinate.x = (otherVertex0.textureCoordinate.x + otherVertex1.textureCoordinate.x) / 2; + newPoleVertex.textureCoordinate.y = poleVertex.textureCoordinate.y; + + if (!overwrittenPoleVertex) + { + vertices[poleIndex] = newPoleVertex; + overwrittenPoleVertex = true; + } + else + { + CheckIndexOverflow(vertices.size()); + + *pPoleIndex = static_cast(vertices.size()); + vertices.push_back(newPoleVertex); + } + } + }; + + fixPole(northPoleIndex); + fixPole(southPoleIndex); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Cylinder / Cone +//-------------------------------------------------------------------------------------- +namespace +{ + // Helper computes a point on a unit circle, aligned to the x/z plane and centered on the origin. + inline XMVECTOR GetCircleVector(size_t i, size_t tessellation) + { + float angle = i * XM_2PI / tessellation; + float dx, dz; + + XMScalarSinCos(&dx, &dz, angle); + + XMVECTORF32 v = { dx, 0, dz, 0 }; + return v; + } + + inline XMVECTOR GetCircleTangent(size_t i, size_t tessellation) + { + float angle = (i * XM_2PI / tessellation) + XM_PIDIV2; + float dx, dz; + + XMScalarSinCos(&dx, &dz, angle); + + XMVECTORF32 v = { dx, 0, dz, 0 }; + return v; + } + + + // Helper creates a triangle fan to close the end of a cylinder / cone + void CreateCylinderCap(VertexCollection& vertices, IndexCollection& indices, size_t tessellation, float height, float radius, bool isTop) + { + // Create cap indices. + for (size_t i = 0; i < tessellation - 2; i++) + { + size_t i1 = (i + 1) % tessellation; + size_t i2 = (i + 2) % tessellation; + + if (isTop) + { + std::swap(i1, i2); + } + + size_t vbase = vertices.size(); + index_push_back(indices, vbase); + index_push_back(indices, vbase + i1); + index_push_back(indices, vbase + i2); + } + + // Which end of the cylinder is this? + XMVECTOR normal = g_XMIdentityR1; + XMVECTOR textureScale = g_XMNegativeOneHalf; + + if (!isTop) + { + normal = -normal; + textureScale *= g_XMNegateX; + } + + // Create cap vertices. + for (size_t i = 0; i < tessellation; i++) + { + XMVECTOR circleVector = GetCircleVector(i, tessellation); + + XMVECTOR position = (circleVector * radius) + (normal * height); + + XMVECTOR textureCoordinate = XMVectorMultiplyAdd(XMVectorSwizzle<0, 2, 3, 3>(circleVector), textureScale, g_XMOneHalf); + + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + } + } +} + +void DirectX::ComputeCylinder(VertexCollection& vertices, IndexCollection& indices, float height, float diameter, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + height /= 2; + + XMVECTOR topOffset = g_XMIdentityR1 * height; + + float radius = diameter / 2; + size_t stride = tessellation + 1; + + // Create a ring of triangles around the outside of the cylinder. + for (size_t i = 0; i <= tessellation; i++) + { + XMVECTOR normal = GetCircleVector(i, tessellation); + + XMVECTOR sideOffset = normal * radius; + + float u = (float)i / tessellation; + + XMVECTOR textureCoordinate = XMLoadFloat(&u); + + vertices.push_back(VertexPositionNormalTexture(sideOffset + topOffset, normal, textureCoordinate)); + vertices.push_back(VertexPositionNormalTexture(sideOffset - topOffset, normal, textureCoordinate + g_XMIdentityR1)); + + index_push_back(indices, i * 2); + index_push_back(indices, (i * 2 + 2) % (stride * 2)); + index_push_back(indices, i * 2 + 1); + + index_push_back(indices, i * 2 + 1); + index_push_back(indices, (i * 2 + 2) % (stride * 2)); + index_push_back(indices, (i * 2 + 3) % (stride * 2)); + } + + // Create flat triangle fan caps to seal the top and bottom. + CreateCylinderCap(vertices, indices, tessellation, height, radius, true); + CreateCylinderCap(vertices, indices, tessellation, height, radius, false); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +// Creates a cone primitive. +void DirectX::ComputeCone(VertexCollection& vertices, IndexCollection& indices, float diameter, float height, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + height /= 2; + + XMVECTOR topOffset = g_XMIdentityR1 * height; + + float radius = diameter / 2; + size_t stride = tessellation + 1; + + // Create a ring of triangles around the outside of the cone. + for (size_t i = 0; i <= tessellation; i++) + { + XMVECTOR circlevec = GetCircleVector(i, tessellation); + + XMVECTOR sideOffset = circlevec * radius; + + float u = (float)i / tessellation; + + XMVECTOR textureCoordinate = XMLoadFloat(&u); + + XMVECTOR pt = sideOffset - topOffset; + + XMVECTOR normal = XMVector3Cross(GetCircleTangent(i, tessellation), topOffset - pt); + normal = XMVector3Normalize(normal); + + // Duplicate the top vertex for distinct normals + vertices.push_back(VertexPositionNormalTexture(topOffset, normal, g_XMZero)); + vertices.push_back(VertexPositionNormalTexture(pt, normal, textureCoordinate + g_XMIdentityR1)); + + index_push_back(indices, i * 2); + index_push_back(indices, (i * 2 + 3) % (stride * 2)); + index_push_back(indices, (i * 2 + 1) % (stride * 2)); + } + + // Create flat triangle fan caps to seal the bottom. + CreateCylinderCap(vertices, indices, tessellation, height, radius, false); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Torus +//-------------------------------------------------------------------------------------- +void DirectX::ComputeTorus(VertexCollection& vertices, IndexCollection& indices, float diameter, float thickness, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + size_t stride = tessellation + 1; + + // First we loop around the main ring of the torus. + for (size_t i = 0; i <= tessellation; i++) + { + float u = (float)i / tessellation; + + float outerAngle = i * XM_2PI / tessellation - XM_PIDIV2; + + // Create a transform matrix that will align geometry to + // slice perpendicularly though the current ring position. + XMMATRIX transform = XMMatrixTranslation(diameter / 2, 0, 0) * XMMatrixRotationY(outerAngle); + + // Now we loop along the other axis, around the side of the tube. + for (size_t j = 0; j <= tessellation; j++) + { + float v = 1 - (float)j / tessellation; + + float innerAngle = j * XM_2PI / tessellation + XM_PI; + float dx, dy; + + XMScalarSinCos(&dy, &dx, innerAngle); + + // Create a vertex. + XMVECTOR normal = XMVectorSet(dx, dy, 0, 0); + XMVECTOR position = normal * thickness / 2; + XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); + + position = XMVector3Transform(position, transform); + normal = XMVector3TransformNormal(normal, transform); + + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + + // And create indices for two triangles. + size_t nextI = (i + 1) % stride; + size_t nextJ = (j + 1) % stride; + + index_push_back(indices, i * stride + j); + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + j); + + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + nextJ); + index_push_back(indices, nextI * stride + j); + } + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Tetrahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const XMVECTORF32 verts[4] = + { + { 0.f, 0.f, 1.f }, + { 2.f*SQRT2 / 3.f, 0.f, -1.f / 3.f }, + { -SQRT2 / 3.f, SQRT6 / 3.f, -1.f / 3.f }, + { -SQRT2 / 3.f, -SQRT6 / 3.f, -1.f / 3.f } + }; + + static const uint32_t faces[4 * 3] = + { + 0, 1, 2, + 0, 2, 3, + 0, 3, 1, + 1, 3, 2, + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1 */)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 4 * 3); + assert(indices.size() == 4 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Octahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeOctahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const XMVECTORF32 verts[6] = + { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 } + }; + + static const uint32_t faces[8 * 3] = + { + 4, 0, 2, + 4, 2, 1, + 4, 1, 3, + 4, 3, 0, + 5, 2, 0, + 5, 1, 2, + 5, 3, 1, + 5, 0, 3 + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1*/)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 8 * 3); + assert(indices.size() == 8 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Dodecahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const float a = 1.f / SQRT3; + static const float b = 0.356822089773089931942f; // sqrt( ( 3 - sqrt(5) ) / 6 ) + static const float c = 0.934172358962715696451f; // sqrt( ( 3 + sqrt(5) ) / 6 ); + + static const XMVECTORF32 verts[20] = + { + { a, a, a }, + { a, a, -a }, + { a, -a, a }, + { a, -a, -a }, + { -a, a, a }, + { -a, a, -a }, + { -a, -a, a }, + { -a, -a, -a }, + { b, c, 0 }, + { -b, c, 0 }, + { b, -c, 0 }, + { -b, -c, 0 }, + { c, 0, b }, + { c, 0, -b }, + { -c, 0, b }, + { -c, 0, -b }, + { 0, b, c }, + { 0, -b, c }, + { 0, b, -c }, + { 0, -b, -c } + }; + + static const uint32_t faces[12 * 5] = + { + 0, 8, 9, 4, 16, + 0, 16, 17, 2, 12, + 12, 2, 10, 3, 13, + 9, 5, 15, 14, 4, + 3, 19, 18, 1, 13, + 7, 11, 6, 14, 15, + 0, 12, 13, 1, 8, + 8, 1, 18, 5, 9, + 16, 4, 14, 6, 17, + 6, 11, 10, 2, 17, + 7, 15, 5, 18, 19, + 7, 19, 3, 10, 11, + }; + + static const XMVECTORF32 textureCoordinates[5] = + { + { 0.654508f, 0.0244717f }, + { 0.0954915f, 0.206107f }, + { 0.0954915f, 0.793893f }, + { 0.654508f, 0.975528f }, + { 1.f, 0.5f } + }; + + static const uint32_t textureIndex[12][5] = + { + { 0, 1, 2, 3, 4 }, + { 2, 3, 4, 0, 1 }, + { 4, 0, 1, 2, 3 }, + { 1, 2, 3, 4, 0 }, + { 2, 3, 4, 0, 1 }, + { 0, 1, 2, 3, 4 }, + { 1, 2, 3, 4, 0 }, + { 4, 0, 1, 2, 3 }, + { 4, 0, 1, 2, 3 }, + { 1, 2, 3, 4, 0 }, + { 0, 1, 2, 3, 4 }, + { 2, 3, 4, 0, 1 }, + }; + + size_t t = 0; + for (size_t j = 0; j < _countof(faces); j += 5, ++t) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + uint32_t v3 = faces[j + 3]; + uint32_t v4 = faces[j + 4]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + index_push_back(indices, base); + index_push_back(indices, base + 2); + index_push_back(indices, base + 3); + + index_push_back(indices, base); + index_push_back(indices, base + 3); + index_push_back(indices, base + 4); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][0]])); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][1]])); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][2]])); + + position = XMVectorScale(verts[v3], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][3]])); + + position = XMVectorScale(verts[v4], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][4]])); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 12 * 5); + assert(indices.size() == 12 * 3 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Icosahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const float t = 1.618033988749894848205f; // (1 + sqrt(5)) / 2 + static const float t2 = 1.519544995837552493271f; // sqrt( 1 + sqr( (1 + sqrt(5)) / 2 ) ) + + static const XMVECTORF32 verts[12] = + { + { t / t2, 1.f / t2, 0 }, + { -t / t2, 1.f / t2, 0 }, + { t / t2, -1.f / t2, 0 }, + { -t / t2, -1.f / t2, 0 }, + { 1.f / t2, 0, t / t2 }, + { 1.f / t2, 0, -t / t2 }, + { -1.f / t2, 0, t / t2 }, + { -1.f / t2, 0, -t / t2 }, + { 0, t / t2, 1.f / t2 }, + { 0, -t / t2, 1.f / t2 }, + { 0, t / t2, -1.f / t2 }, + { 0, -t / t2, -1.f / t2 } + }; + + static const uint32_t faces[20 * 3] = + { + 0, 8, 4, + 0, 5, 10, + 2, 4, 9, + 2, 11, 5, + 1, 6, 8, + 1, 10, 7, + 3, 9, 6, + 3, 7, 11, + 0, 10, 8, + 1, 8, 10, + 2, 9, 11, + 3, 11, 9, + 4, 2, 0, + 5, 0, 2, + 6, 1, 3, + 7, 3, 1, + 8, 6, 4, + 9, 4, 6, + 10, 5, 7, + 11, 7, 5 + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1 */)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 20 * 3); + assert(indices.size() == 20 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Teapot +//-------------------------------------------------------------------------------------- + +// Include the teapot control point data. +namespace +{ +#include "TeapotData.inc" + + // Tessellates the specified bezier patch. + void XM_CALLCONV TessellatePatch(VertexCollection& vertices, IndexCollection& indices, TeapotPatch const& patch, size_t tessellation, FXMVECTOR scale, bool isMirrored) + { + // Look up the 16 control points for this patch. + XMVECTOR controlPoints[16]; + + for (int i = 0; i < 16; i++) + { + controlPoints[i] = TeapotControlPoints[patch.indices[i]] * scale; + } + + // Create the index data. + size_t vbase = vertices.size(); + Bezier::CreatePatchIndices(tessellation, isMirrored, [&](size_t index) + { + index_push_back(indices, vbase + index); + }); + + // Create the vertex data. + Bezier::CreatePatchVertices(controlPoints, tessellation, isMirrored, [&](FXMVECTOR position, FXMVECTOR normal, FXMVECTOR textureCoordinate) + { + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + }); + } +} + + +// Creates a teapot primitive. +void DirectX::ComputeTeapot(VertexCollection& vertices, IndexCollection& indices, float size, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 1) + throw std::out_of_range("tesselation parameter out of range"); + + XMVECTOR scaleVector = XMVectorReplicate(size); + + XMVECTOR scaleNegateX = scaleVector * g_XMNegateX; + XMVECTOR scaleNegateZ = scaleVector * g_XMNegateZ; + XMVECTOR scaleNegateXZ = scaleVector * g_XMNegateX * g_XMNegateZ; + + for (int i = 0; i < sizeof(TeapotPatches) / sizeof(TeapotPatches[0]); i++) + { + TeapotPatch const& patch = TeapotPatches[i]; + + // Because the teapot is symmetrical from left to right, we only store + // data for one side, then tessellate each patch twice, mirroring in X. + TessellatePatch(vertices, indices, patch, tessellation, scaleVector, false); + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateX, true); + + if (patch.mirrorZ) + { + // Some parts of the teapot (the body, lid, and rim, but not the + // handle or spout) are also symmetrical from front to back, so + // we tessellate them four times, mirroring in Z as well as X. + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateZ, true); + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateXZ, false); + } + } + + // Built RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} \ No newline at end of file diff --git a/Kits/DirectXTK/Src/Geometry.h b/Kits/DirectXTK/Src/Geometry.h new file mode 100644 index 00000000..2afc7d0f --- /dev/null +++ b/Kits/DirectXTK/Src/Geometry.h @@ -0,0 +1,32 @@ +//-------------------------------------------------------------------------------------- +// File: Geometry.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "VertexTypes.h" + +namespace DirectX +{ + typedef std::vector VertexCollection; + typedef std::vector IndexCollection; + + void ComputeBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords, bool invertn); + void ComputeSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn); + void ComputeGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords); + void ComputeCylinder(VertexCollection& vertices, IndexCollection& indices, float height, float diameter, size_t tessellation, bool rhcoords); + void ComputeCone(VertexCollection& vertices, IndexCollection& indices, float diameter, float height, size_t tessellation, bool rhcoords); + void ComputeTorus(VertexCollection& vertices, IndexCollection& indices, float diameter, float thickness, size_t tessellation, bool rhcoords); + void ComputeTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeOctahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeTeapot(VertexCollection& vertices, IndexCollection& indices, float size, size_t tessellation, bool rhcoords); +} \ No newline at end of file diff --git a/Kits/DirectXTK/Src/LoaderHelpers.h b/Kits/DirectXTK/Src/LoaderHelpers.h new file mode 100644 index 00000000..c12c0fe7 --- /dev/null +++ b/Kits/DirectXTK/Src/LoaderHelpers.h @@ -0,0 +1,858 @@ +//-------------------------------------------------------------------------------------- +// File: LoaderHelpers.h +// +// Helper functions for texture loaders and screen grabber +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DDS.h" +#include "DDSTextureLoader.h" + + +namespace DirectX +{ + //-------------------------------------------------------------------------------------- + // Return the BPP for a particular format + //-------------------------------------------------------------------------------------- + inline size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_YUY2: + return 32; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + return 24; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_NV11: + return 12; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return 32; + + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: + return 24; + + case DXGI_FORMAT_R4G4_UNORM: + return 8; + +#endif // _XBOX_ONE && _TITLE + + default: + return 0; + } + } + + //-------------------------------------------------------------------------------------- + inline DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } + } + + //-------------------------------------------------------------------------------------- + inline bool IsCompressed(_In_ DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + + default: + return false; + } + } + + //-------------------------------------------------------------------------------------- + inline DXGI_FORMAT EnsureNotTypeless(DXGI_FORMAT fmt) + { + // Assumes UNORM or FLOAT; doesn't use UINT or SINT + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_FLOAT; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: return DXGI_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R32G32_TYPELESS: return DXGI_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: return DXGI_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_R16G16_TYPELESS: return DXGI_FORMAT_R16G16_UNORM; + case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R8G8_TYPELESS: return DXGI_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_TYPELESS: return DXGI_FORMAT_R16_UNORM; + case DXGI_FORMAT_R8_TYPELESS: return DXGI_FORMAT_R8_UNORM; + case DXGI_FORMAT_BC1_TYPELESS: return DXGI_FORMAT_BC1_UNORM; + case DXGI_FORMAT_BC2_TYPELESS: return DXGI_FORMAT_BC2_UNORM; + case DXGI_FORMAT_BC3_TYPELESS: return DXGI_FORMAT_BC3_UNORM; + case DXGI_FORMAT_BC4_TYPELESS: return DXGI_FORMAT_BC4_UNORM; + case DXGI_FORMAT_BC5_TYPELESS: return DXGI_FORMAT_BC5_UNORM; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8X8_UNORM; + case DXGI_FORMAT_BC7_TYPELESS: return DXGI_FORMAT_BC7_UNORM; + default: return fmt; + } + } + + //-------------------------------------------------------------------------------------- + inline HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t* fileName, + std::unique_ptr& ddsData, + DDS_HEADER** header, + uint8_t** bitData, + size_t* bitSize + ) + { + if (!header || !bitData || !bitSize) + { + return E_POINTER; + } + + // open the file +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(fileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr))); +#endif + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read + if (fileInfo.EndOfFile.HighPart > 0) + { + return E_FAIL; + } + + // Need at least enough data to fill the header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // create enough space for the file data + ddsData.reset(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]); + if (!ddsData) + { + return E_OUTOFMEMORY; + } + + // read the data in + DWORD BytesRead = 0; + if (!ReadFile(hFile.get(), + ddsData.get(), + fileInfo.EndOfFile.LowPart, + &BytesRead, + nullptr + )) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (BytesRead < fileInfo.EndOfFile.LowPart) + { + return E_FAIL; + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto hdr = reinterpret_cast(ddsData.get() + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (hdr->size != sizeof(DDS_HEADER) || + hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for DX10 extension + bool bDXT10Header = false; + if ((hdr->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) + { + // Must be long enough for both headers and magic value + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) + { + return E_FAIL; + } + + bDXT10Header = true; + } + + // setup the pointers in the process request + *header = hdr; + ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0); + *bitData = ddsData.get() + offset; + *bitSize = fileInfo.EndOfFile.LowPart - offset; + + return S_OK; + } + + //-------------------------------------------------------------------------------------- + // Get surface information for a particular format + //-------------------------------------------------------------------------------------- + inline void GetSurfaceInfo(_In_ size_t width, + _In_ size_t height, + _In_ DXGI_FORMAT fmt, + _Out_opt_ size_t* outNumBytes, + _Out_opt_ size_t* outRowBytes, + _Out_opt_ size_t* outNumRows) + { + size_t numBytes = 0; + size_t rowBytes = 0; + size_t numRows = 0; + + bool bc = false; + bool packed = false; + bool planar = false; + size_t bpe = 0; + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + bc = true; + bpe = 8; + break; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + bc = true; + bpe = 16; + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_YUY2: + packed = true; + bpe = 4; + break; + + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + packed = true; + bpe = 8; + break; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + planar = true; + bpe = 2; + break; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + planar = true; + bpe = 4; + break; + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: + planar = true; + bpe = 4; + break; + +#endif + } + + if (bc) + { + size_t numBlocksWide = 0; + if (width > 0) + { + numBlocksWide = std::max(1, (width + 3) / 4); + } + size_t numBlocksHigh = 0; + if (height > 0) + { + numBlocksHigh = std::max(1, (height + 3) / 4); + } + rowBytes = numBlocksWide * bpe; + numRows = numBlocksHigh; + numBytes = rowBytes * numBlocksHigh; + } + else if (packed) + { + rowBytes = ((width + 1) >> 1) * bpe; + numRows = height; + numBytes = rowBytes * height; + } + else if (fmt == DXGI_FORMAT_NV11) + { + rowBytes = ((width + 3) >> 2) * 4; + numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data + numBytes = rowBytes * numRows; + } + else if (planar) + { + rowBytes = ((width + 1) >> 1) * bpe; + numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1); + numRows = height + ((height + 1) >> 1); + } + else + { + size_t bpp = BitsPerPixel(fmt); + rowBytes = (width * bpp + 7) / 8; // round up to nearest byte + numRows = height; + numBytes = rowBytes * height; + } + + if (outNumBytes) + { + *outNumBytes = numBytes; + } + if (outRowBytes) + { + *outRowBytes = rowBytes; + } + if (outNumRows) + { + *outNumRows = numRows; + } + } + + //-------------------------------------------------------------------------------------- + #define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a ) + + inline DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf) + { + if (ddpf.flags & DDS_RGB) + { + // Note that sRGB formats are written using the "DX10" extended header + + switch (ddpf.RGBBitCount) + { + case 32: + if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + { + return DXGI_FORMAT_R8G8B8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) + { + return DXGI_FORMAT_B8G8R8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000)) + { + return DXGI_FORMAT_B8G8R8X8_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8 + + // Note that many common DDS reader/writers (including D3DX) swap the + // the RED/BLUE masks for 10:10:10:2 formats. We assume + // below that the 'backwards' header mask is being used since it is most + // likely written by D3DX. The more robust solution is to use the 'DX10' + // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly + + // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data + if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000)) + { + return DXGI_FORMAT_R10G10B10A2_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10 + + if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16G16_UNORM; + } + + if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000)) + { + // Only 32-bit color channel format in D3D9 was R32F + return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 + } + break; + + case 24: + // No 24bpp DXGI formats aka D3DFMT_R8G8B8 + break; + + case 16: + if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000)) + { + return DXGI_FORMAT_B5G5R5A1_UNORM; + } + if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000)) + { + return DXGI_FORMAT_B5G6R5_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5 + + if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000)) + { + return DXGI_FORMAT_B4G4R4A4_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4 + + // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc. + break; + } + } + else if (ddpf.flags & DDS_LUMINANCE) + { + if (8 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + + // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 + } + + if (16 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension + } + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) + { + return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + } + } + else if (ddpf.flags & DDS_ALPHA) + { + if (8 == ddpf.RGBBitCount) + { + return DXGI_FORMAT_A8_UNORM; + } + } + else if (ddpf.flags & DDS_BUMPDUDV) + { + if (16 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x00ff, 0xff00, 0x0000, 0x0000)) + { + return DXGI_FORMAT_R8G8_SNORM; // D3DX10/11 writes this out as DX10 extension + } + } + + if (32 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + { + return DXGI_FORMAT_R8G8B8A8_SNORM; // D3DX10/11 writes this out as DX10 extension + } + if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16G16_SNORM; // D3DX10/11 writes this out as DX10 extension + } + + // No DXGI format maps to ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) aka D3DFMT_A2W10V10U10 + } + } + else if (ddpf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC1_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + // While pre-multiplied alpha isn't directly supported by the DXGI formats, + // they are basically the same as these BC formats so they can be mapped + if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_SNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_SNORM; + } + + // BC6H and BC7 are written using the "DX10" extended header + + if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC) + { + return DXGI_FORMAT_R8G8_B8G8_UNORM; + } + if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC) + { + return DXGI_FORMAT_G8R8_G8B8_UNORM; + } + + if (MAKEFOURCC('Y', 'U', 'Y', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_YUY2; + } + + // Check for D3DFORMAT enums being set here + switch (ddpf.fourCC) + { + case 36: // D3DFMT_A16B16G16R16 + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case 110: // D3DFMT_Q16W16V16U16 + return DXGI_FORMAT_R16G16B16A16_SNORM; + + case 111: // D3DFMT_R16F + return DXGI_FORMAT_R16_FLOAT; + + case 112: // D3DFMT_G16R16F + return DXGI_FORMAT_R16G16_FLOAT; + + case 113: // D3DFMT_A16B16G16R16F + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case 114: // D3DFMT_R32F + return DXGI_FORMAT_R32_FLOAT; + + case 115: // D3DFMT_G32R32F + return DXGI_FORMAT_R32G32_FLOAT; + + case 116: // D3DFMT_A32B32G32R32F + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + + return DXGI_FORMAT_UNKNOWN; + } + + #undef ISBITMASK + + //-------------------------------------------------------------------------------------- + inline DirectX::DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) + { + if (header->ddspf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC) + { + auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); + auto mode = static_cast(d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK); + switch (mode) + { + case DDS_ALPHA_MODE_STRAIGHT: + case DDS_ALPHA_MODE_PREMULTIPLIED: + case DDS_ALPHA_MODE_OPAQUE: + case DDS_ALPHA_MODE_CUSTOM: + return mode; + } + } + else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC) + || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC)) + { + return DDS_ALPHA_MODE_PREMULTIPLIED; + } + } + + return DDS_ALPHA_MODE_UNKNOWN; + } + + //-------------------------------------------------------------------------------------- + class auto_delete_file + { + public: + auto_delete_file(HANDLE hFile) : m_handle(hFile) {} + + auto_delete_file(const auto_delete_file&) = delete; + auto_delete_file& operator=(const auto_delete_file&) = delete; + + ~auto_delete_file() + { + if (m_handle) + { + FILE_DISPOSITION_INFO info = {}; + info.DeleteFile = TRUE; + (void)SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, sizeof(info)); + } + } + + void clear() { m_handle = 0; } + + private: + HANDLE m_handle; + }; + + class auto_delete_file_wic + { + public: + auto_delete_file_wic(Microsoft::WRL::ComPtr& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {} + + auto_delete_file_wic(const auto_delete_file_wic&) = delete; + auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete; + + ~auto_delete_file_wic() + { + if (m_filename) + { + m_handle.Reset(); + DeleteFileW(m_filename); + } + } + + void clear() { m_filename = 0; } + + private: + LPCWSTR m_filename; + Microsoft::WRL::ComPtr& m_handle; + }; +} \ No newline at end of file diff --git a/Kits/DirectXTK/Src/ModelLoadSDKMESH.cpp b/Kits/DirectXTK/Src/ModelLoadSDKMESH.cpp index 497dc1ed..b0e9e699 100644 --- a/Kits/DirectXTK/Src/ModelLoadSDKMESH.cpp +++ b/Kits/DirectXTK/Src/ModelLoadSDKMESH.cpp @@ -21,621 +21,280 @@ #include "PlatformHelpers.h" #include "BinaryReader.h" +#include "SDKMesh.h" + using namespace DirectX; using Microsoft::WRL::ComPtr; -#pragma warning(disable : 4121) - -//-------------------------------------------------------------------------------------- -// SDKMESH format is generated by the legacy DirectX SDK's Content Exporter and -// originally rendered by the DXUT helper class SDKMesh -// -// http://go.microsoft.com/fwlink/?LinkId=226208 -//-------------------------------------------------------------------------------------- -namespace DXUT +namespace { - // .SDKMESH files - - // SDKMESH_HEADER - // SDKMESH_VERTEX_BUFFER_HEADER header->VertexStreamHeadersOffset - // SDKMESH_INDEX_BUFFER_HEADER header->IndexStreamHeadersOffset - // SDKMESH_MESH header->MeshDataOffset - // SDKMESH_SUBSET header->SubsetDataOffset - // SDKMESH_FRAME header->FrameDataOffset - // SDKMESH_MATERIAL header->MaterialDataOffset - // [header->NonBufferDataSize] - // { [ header->NumVertexBuffers] - // VB data - // } - // { [ header->NumIndexBuffers] - // IB data - // } - - - // .SDDKANIM files - - // SDKANIMATION_FILE_HEADER - // BYTE[] - Length of fileheader->AnimationDataSize - - // .SDKMESH uses Direct3D 9 decls, but only a subset of these is ever generated by the legacy DirectX SDK Content Exporter - - // D3DDECLUSAGE_POSITION / D3DDECLTYPE_FLOAT3 - // (D3DDECLUSAGE_BLENDWEIGHT / D3DDECLTYPE_UBYTE4N - // D3DDECLUSAGE_BLENDINDICES / D3DDECLTYPE_UBYTE4)? - // (D3DDECLUSAGE_NORMAL / D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_UBYTE4N, or D3DDECLTYPE_DEC3N [not supported])? - // (D3DDECLUSAGE_COLOR / D3DDECLTYPE_D3DCOLOR)? - // (D3DDECLUSAGE_TEXCOORD / D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2 or D3DDECLTYPE_FLOAT16_2, D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_FLOAT4 or D3DDECLTYPE_FLOAT16_4)* - // (D3DDECLUSAGE_TANGENT / same as D3DDECLUSAGE_NORMAL)? - // (D3DDECLUSAGE_BINORMAL / same as D3DDECLUSAGE_NORMAL)? - - enum D3DDECLUSAGE - { - D3DDECLUSAGE_POSITION = 0, - D3DDECLUSAGE_BLENDWEIGHT =1, - D3DDECLUSAGE_BLENDINDICES =2, - D3DDECLUSAGE_NORMAL =3, - D3DDECLUSAGE_TEXCOORD = 5, - D3DDECLUSAGE_TANGENT = 6, - D3DDECLUSAGE_BINORMAL = 7, - D3DDECLUSAGE_COLOR = 10, - }; - - enum D3DDECLTYPE - { - D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) - D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) - D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) - D3DDECLTYPE_FLOAT4 = 3, // 4D float - D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range - // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) - D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte - D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 - D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) - // Note: There is no equivalent to D3DDECLTYPE_DEC3N (14) as a DXGI_FORMAT - D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) - D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values - - D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. - }; - - #pragma pack(push,4) - - struct D3DVERTEXELEMENT9 + struct MaterialRecordSDKMESH { - WORD Stream; // Stream index - WORD Offset; // Offset in the stream in bytes - BYTE Type; // Data type - BYTE Method; // Processing method - BYTE Usage; // Semantics - BYTE UsageIndex; // Semantic index + std::shared_ptr effect; + bool alpha; }; - #pragma pack(pop) - - //-------------------------------------------------------------------------------------- - // Hard Defines for the various structures - //-------------------------------------------------------------------------------------- - const uint32_t SDKMESH_FILE_VERSION = 101; - const uint32_t MAX_VERTEX_ELEMENTS = 32; - const uint32_t MAX_VERTEX_STREAMS = 16; - const uint32_t MAX_FRAME_NAME = 100; - const uint32_t MAX_MESH_NAME = 100; - const uint32_t MAX_SUBSET_NAME = 100; - const uint32_t MAX_MATERIAL_NAME = 100; - const uint32_t MAX_TEXTURE_NAME = MAX_PATH; - const uint32_t MAX_MATERIAL_PATH = MAX_PATH; - const uint32_t INVALID_FRAME = uint32_t(-1); - const uint32_t INVALID_MESH = uint32_t(-1); - const uint32_t INVALID_MATERIAL = uint32_t(-1); - const uint32_t INVALID_SUBSET = uint32_t(-1); - const uint32_t INVALID_ANIMATION_DATA = uint32_t(-1); - const uint32_t INVALID_SAMPLER_SLOT = uint32_t(-1); - const uint32_t ERROR_RESOURCE_VALUE = 1; - - template bool IsErrorResource( TYPE data ) - { - if( ( TYPE )ERROR_RESOURCE_VALUE == data ) - return true; - return false; - } - - //-------------------------------------------------------------------------------------- - // Enumerated Types. These will have mirrors in both D3D9 and D3D11 - //-------------------------------------------------------------------------------------- - enum SDKMESH_PRIMITIVE_TYPE + void LoadMaterial(_In_ const DXUT::SDKMESH_MATERIAL& mh, + _In_ bool perVertexColor, _In_ bool enableSkinning, _In_ bool enableDualTexture, + _Inout_ IEffectFactory& fxFactory, _Inout_ MaterialRecordSDKMESH& m) { - PT_TRIANGLE_LIST = 0, - PT_TRIANGLE_STRIP, - PT_LINE_LIST, - PT_LINE_STRIP, - PT_POINT_LIST, - PT_TRIANGLE_LIST_ADJ, - PT_TRIANGLE_STRIP_ADJ, - PT_LINE_LIST_ADJ, - PT_LINE_STRIP_ADJ, - PT_QUAD_PATCH_LIST, - PT_TRIANGLE_PATCH_LIST, - }; + wchar_t matName[DXUT::MAX_MATERIAL_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.Name, -1, matName, DXUT::MAX_MATERIAL_NAME); - enum SDKMESH_INDEX_TYPE - { - IT_16BIT = 0, - IT_32BIT, - }; + wchar_t txtName[DXUT::MAX_TEXTURE_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.DiffuseTexture, -1, txtName, DXUT::MAX_TEXTURE_NAME); - enum FRAME_TRANSFORM_TYPE - { - FTT_RELATIVE = 0, - FTT_ABSOLUTE, //This is not currently used but is here to support absolute transformations in the future - }; + wchar_t txtName2[DXUT::MAX_TEXTURE_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.SpecularTexture, -1, txtName2, DXUT::MAX_TEXTURE_NAME); - //-------------------------------------------------------------------------------------- - // Structures. - //-------------------------------------------------------------------------------------- - #pragma pack(push,8) + if (!mh.SpecularTexture[0] && enableDualTexture) + { + DebugTrace("WARNING: Material '%s' has multiple texture coords but not multiple textures\n", mh.Name); + enableDualTexture = false; + } - struct SDKMESH_HEADER - { - //Basic Info and sizes - UINT Version; - BYTE IsBigEndian; - UINT64 HeaderSize; - UINT64 NonBufferDataSize; - UINT64 BufferDataSize; - - //Stats - UINT NumVertexBuffers; - UINT NumIndexBuffers; - UINT NumMeshes; - UINT NumTotalSubsets; - UINT NumFrames; - UINT NumMaterials; - - //Offsets to Data - UINT64 VertexStreamHeadersOffset; - UINT64 IndexStreamHeadersOffset; - UINT64 MeshDataOffset; - UINT64 SubsetDataOffset; - UINT64 FrameDataOffset; - UINT64 MaterialDataOffset; - }; + EffectFactory::EffectInfo info; + info.name = matName; + info.perVertexColor = perVertexColor; + info.enableSkinning = enableSkinning; + info.enableDualTexture = enableDualTexture; + info.ambientColor = XMFLOAT3(mh.Ambient.x, mh.Ambient.y, mh.Ambient.z); + info.diffuseColor = XMFLOAT3(mh.Diffuse.x, mh.Diffuse.y, mh.Diffuse.z); + info.emissiveColor = XMFLOAT3(mh.Emissive.x, mh.Emissive.y, mh.Emissive.z); - struct SDKMESH_VERTEX_BUFFER_HEADER - { - UINT64 NumVertices; - UINT64 SizeBytes; - UINT64 StrideBytes; - D3DVERTEXELEMENT9 Decl[MAX_VERTEX_ELEMENTS]; - union + if (mh.Diffuse.w != 1.f && mh.Diffuse.w != 0.f) { - UINT64 DataOffset; - ID3D11Buffer* pVB11; - }; - }; + info.alpha = mh.Diffuse.w; + } + else + info.alpha = 1.f; - struct SDKMESH_INDEX_BUFFER_HEADER - { - UINT64 NumIndices; - UINT64 SizeBytes; - UINT IndexType; - union + if (mh.Power) { - UINT64 DataOffset; - ID3D11Buffer* pIB11; - }; - }; - - struct SDKMESH_MESH - { - char Name[MAX_MESH_NAME]; - BYTE NumVertexBuffers; - UINT VertexBuffers[MAX_VERTEX_STREAMS]; - UINT IndexBuffer; - UINT NumSubsets; - UINT NumFrameInfluences; //aka bones + info.specularPower = mh.Power; + info.specularColor = XMFLOAT3(mh.Specular.x, mh.Specular.y, mh.Specular.z); + } - DirectX::XMFLOAT3 BoundingBoxCenter; - DirectX::XMFLOAT3 BoundingBoxExtents; + info.texture = txtName; + info.texture2 = txtName2; - union - { - UINT64 SubsetOffset; - INT* pSubsets; - }; - union - { - UINT64 FrameInfluenceOffset; - UINT* pFrameInfluences; - }; - }; + m.effect = fxFactory.CreateEffect(info, nullptr); + m.alpha = (info.alpha < 1.f); + } - struct SDKMESH_SUBSET - { - char Name[MAX_SUBSET_NAME]; - UINT MaterialID; - UINT PrimitiveType; - UINT64 IndexStart; - UINT64 IndexCount; - UINT64 VertexStart; - UINT64 VertexCount; - }; - struct SDKMESH_FRAME - { - char Name[MAX_FRAME_NAME]; - UINT Mesh; - UINT ParentFrame; - UINT ChildFrame; - UINT SiblingFrame; - DirectX::XMFLOAT4X4 Matrix; - UINT AnimationDataIndex; //Used to index which set of keyframes transforms this frame - }; + //-------------------------------------------------------------------------------------- + // Direct3D 9 Vertex Declaration to Direct3D 11 Input Layout mapping - struct SDKMESH_MATERIAL + void GetInputLayoutDesc(_In_reads_(32) const DXUT::D3DVERTEXELEMENT9 decl[], std::vector& inputDesc, + bool &perVertexColor, bool& enableSkinning, bool& dualTexture) { - char Name[MAX_MATERIAL_NAME]; - - // Use MaterialInstancePath - char MaterialInstancePath[MAX_MATERIAL_PATH]; - - // Or fall back to d3d8-type materials - char DiffuseTexture[MAX_TEXTURE_NAME]; - char NormalTexture[MAX_TEXTURE_NAME]; - char SpecularTexture[MAX_TEXTURE_NAME]; - - DirectX::XMFLOAT4 Diffuse; - DirectX::XMFLOAT4 Ambient; - DirectX::XMFLOAT4 Specular; - DirectX::XMFLOAT4 Emissive; - FLOAT Power; - - union + static const D3D11_INPUT_ELEMENT_DESC elements[] = { - UINT64 Force64_1; //Force the union to 64bits - ID3D11Texture2D* pDiffuseTexture11; - }; - union - { - UINT64 Force64_2; //Force the union to 64bits - ID3D11Texture2D* pNormalTexture11; - }; - union - { - UINT64 Force64_3; //Force the union to 64bits - ID3D11Texture2D* pSpecularTexture11; + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "BLENDINDICES",0, DXGI_FORMAT_R8G8B8A8_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "BLENDWEIGHT", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - union - { - UINT64 Force64_4; //Force the union to 64bits - ID3D11ShaderResourceView* pDiffuseRV11; - }; - union - { - UINT64 Force64_5; //Force the union to 64bits - ID3D11ShaderResourceView* pNormalRV11; - }; - union - { - UINT64 Force64_6; //Force the union to 64bits - ID3D11ShaderResourceView* pSpecularRV11; - }; - }; + using namespace DXUT; - struct SDKANIMATION_FILE_HEADER - { - UINT Version; - BYTE IsBigEndian; - UINT FrameTransformType; - UINT NumFrames; - UINT NumAnimationKeys; - UINT AnimationFPS; - UINT64 AnimationDataSize; - UINT64 AnimationDataOffset; - }; + uint32_t offset = 0; + uint32_t texcoords = 0; - struct SDKANIMATION_DATA - { - DirectX::XMFLOAT3 Translation; - DirectX::XMFLOAT4 Orientation; - DirectX::XMFLOAT3 Scaling; - }; + bool posfound = false; - struct SDKANIMATION_FRAME_DATA - { - char FrameName[MAX_FRAME_NAME]; - union + for (uint32_t index = 0; index < DXUT::MAX_VERTEX_ELEMENTS; ++index) { - UINT64 DataOffset; - SDKANIMATION_DATA* pAnimationData; - }; - }; - - #pragma pack(pop) - -}; // namespace - -static_assert( sizeof(DXUT::D3DVERTEXELEMENT9) == 8, "Direct3D9 Decl structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_HEADER)== 104, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) == 288, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER) == 32, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_MESH) == 224, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_SUBSET) == 144, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_FRAME) == 184, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKMESH_MATERIAL) == 1256, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKANIMATION_FILE_HEADER) == 40, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKANIMATION_DATA) == 40, "SDK Mesh structure size incorrect" ); -static_assert( sizeof(DXUT::SDKANIMATION_FRAME_DATA) == 112, "SDK Mesh structure size incorrect" ); - - -//-------------------------------------------------------------------------------------- -struct MaterialRecordSDKMESH -{ - std::shared_ptr effect; - bool alpha; -}; - - -static void LoadMaterial( _In_ const DXUT::SDKMESH_MATERIAL& mh, - _In_ bool perVertexColor, _In_ bool enableSkinning, _In_ bool enableDualTexture, - _Inout_ IEffectFactory& fxFactory, _Inout_ MaterialRecordSDKMESH& m ) -{ - wchar_t matName[ DXUT::MAX_MATERIAL_NAME ]; - MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, mh.Name, -1, matName, DXUT::MAX_MATERIAL_NAME ); - - wchar_t txtName[ DXUT::MAX_TEXTURE_NAME ]; - MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, mh.DiffuseTexture, -1, txtName, DXUT::MAX_TEXTURE_NAME ); - - wchar_t txtName2[ DXUT::MAX_TEXTURE_NAME ]; - MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, mh.SpecularTexture, -1, txtName2, DXUT::MAX_TEXTURE_NAME ); - - if ( !mh.SpecularTexture[0] && enableDualTexture ) - { - DebugTrace("WARNING: Material '%s' has multiple texture coords but not multiple textures\n", mh.Name); - enableDualTexture = false; - } - - EffectFactory::EffectInfo info; - info.name = matName; - info.perVertexColor = perVertexColor; - info.enableSkinning = enableSkinning; - info.enableDualTexture = enableDualTexture; - info.ambientColor = XMFLOAT3( mh.Ambient.x, mh.Ambient.y, mh.Ambient.z ); - info.diffuseColor = XMFLOAT3( mh.Diffuse.x, mh.Diffuse.y, mh.Diffuse.z ); - info.emissiveColor= XMFLOAT3( mh.Emissive.x, mh.Emissive.y, mh.Emissive.z ); - - if ( mh.Diffuse.w != 1.f && mh.Diffuse.w != 0.f ) - { - info.alpha = mh.Diffuse.w; - } - else - info.alpha = 1.f; - - if ( mh.Power ) - { - info.specularPower = mh.Power; - info.specularColor = XMFLOAT3( mh.Specular.x, mh.Specular.y, mh.Specular.z ); - } - - info.texture = txtName; - info.texture2 = txtName2; - - m.effect = fxFactory.CreateEffect( info, nullptr ); - m.alpha = (info.alpha < 1.f); -} - - -//-------------------------------------------------------------------------------------- -// Direct3D 9 Vertex Declaration to DirectInput 11 Input Layout mapping - -static void GetInputLayoutDesc( _In_reads_(32) const DXUT::D3DVERTEXELEMENT9 decl[], std::vector& inputDesc, - bool &perVertexColor, bool& enableSkinning, bool& dualTexture ) -{ - static const D3D11_INPUT_ELEMENT_DESC elements[] = - { - { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "BLENDINDICES",0, DXGI_FORMAT_R8G8B8A8_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "BLENDWEIGHT", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - using namespace DXUT; - - uint32_t offset = 0; - uint32_t texcoords = 0; - - bool posfound = false; - - for( uint32_t index = 0; index < DXUT::MAX_VERTEX_ELEMENTS; ++index ) - { - if ( decl[index].Usage == 0xFF ) - break; + if (decl[index].Usage == 0xFF) + break; - if ( decl[index].Type == D3DDECLTYPE_UNUSED ) - break; + if (decl[index].Type == D3DDECLTYPE_UNUSED) + break; - if ( decl[index].Offset != offset ) - break; + if (decl[index].Offset != offset) + break; - if ( decl[index].Usage == D3DDECLUSAGE_POSITION && decl[index].Type == D3DDECLTYPE_FLOAT3 ) - { - inputDesc.push_back( elements[0] ); - offset += 12; - posfound = true; - } - else if ( decl[index].Usage == D3DDECLUSAGE_NORMAL ) - { - if ( decl[index].Type == D3DDECLTYPE_FLOAT3 ) + if (decl[index].Usage == D3DDECLUSAGE_POSITION && decl[index].Type == D3DDECLTYPE_FLOAT3) { - inputDesc.push_back( elements[1] ); + inputDesc.push_back(elements[0]); offset += 12; + posfound = true; } - else if ( decl[index].Type == D3DDECLTYPE_FLOAT16_4 ) - { - D3D11_INPUT_ELEMENT_DESC desc = elements[1]; - desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; - inputDesc.push_back( desc ); - offset += 8; - } - else if ( decl[index].Type == D3DDECLTYPE_SHORT4N ) + else if (decl[index].Usage == D3DDECLUSAGE_NORMAL) { - D3D11_INPUT_ELEMENT_DESC desc = elements[1]; - desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; - inputDesc.push_back( desc ); - offset += 8; + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[1]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; } - else if ( decl[index].Type == D3DDECLTYPE_UBYTE4N ) + else if (decl[index].Usage == D3DDECLUSAGE_COLOR && decl[index].Type == D3DDECLTYPE_D3DCOLOR) { - D3D11_INPUT_ELEMENT_DESC desc = elements[1]; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - inputDesc.push_back( desc ); + inputDesc.push_back(elements[2]); offset += 4; + perVertexColor = true; } - else - break; - } - else if ( decl[index].Usage == D3DDECLUSAGE_COLOR && decl[index].Type == D3DDECLTYPE_D3DCOLOR ) - { - inputDesc.push_back( elements[2] ); - offset += 4; - perVertexColor = true; - } - else if ( decl[index].Usage == D3DDECLUSAGE_TANGENT ) - { - if ( decl[index].Type == D3DDECLTYPE_FLOAT3 ) + else if (decl[index].Usage == D3DDECLUSAGE_TANGENT) { - inputDesc.push_back( elements[3] ); - offset += 12; + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[3]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; } - else if ( decl[index].Type == D3DDECLTYPE_FLOAT16_4 ) + else if (decl[index].Usage == D3DDECLUSAGE_BINORMAL) { - D3D11_INPUT_ELEMENT_DESC desc = elements[3]; - desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; - inputDesc.push_back( desc ); - offset += 8; + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[4]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D11_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; } - else if ( decl[index].Type == D3DDECLTYPE_SHORT4N ) + else if (decl[index].Usage == D3DDECLUSAGE_TEXCOORD) { - D3D11_INPUT_ELEMENT_DESC desc = elements[3]; - desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; - inputDesc.push_back( desc ); - offset += 8; + D3D11_INPUT_ELEMENT_DESC desc = elements[5]; + desc.SemanticIndex = decl[index].UsageIndex; + + bool unk = false; + switch (decl[index].Type) + { + case D3DDECLTYPE_FLOAT2: offset += 8; break; + case D3DDECLTYPE_FLOAT1: desc.Format = DXGI_FORMAT_R32_FLOAT; offset += 4; break; + case D3DDECLTYPE_FLOAT3: desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; offset += 12; break; + case D3DDECLTYPE_FLOAT4: desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; offset += 16; break; + case D3DDECLTYPE_FLOAT16_2: desc.Format = DXGI_FORMAT_R16G16_FLOAT; offset += 4; break; + case D3DDECLTYPE_FLOAT16_4: desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; offset += 8; break; + + default: + unk = true; + break; + } + + if (unk) + break; + + ++texcoords; + + inputDesc.push_back(desc); } - else if ( decl[index].Type == D3DDECLTYPE_UBYTE4N ) + else if (decl[index].Usage == D3DDECLUSAGE_BLENDINDICES && decl[index].Type == D3DDECLTYPE_UBYTE4) { - D3D11_INPUT_ELEMENT_DESC desc = elements[3]; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - inputDesc.push_back( desc ); + enableSkinning = true; + inputDesc.push_back(elements[6]); offset += 4; } - else - break; - } - else if ( decl[index].Usage == D3DDECLUSAGE_BINORMAL ) - { - if ( decl[index].Type == D3DDECLTYPE_FLOAT3 ) - { - inputDesc.push_back( elements[4] ); - offset += 12; - } - else if ( decl[index].Type == D3DDECLTYPE_FLOAT16_4 ) + else if (decl[index].Usage == D3DDECLUSAGE_BLENDWEIGHT && decl[index].Type == D3DDECLTYPE_UBYTE4N) { - D3D11_INPUT_ELEMENT_DESC desc = elements[4]; - desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; - inputDesc.push_back( desc ); - offset += 8; - } - else if ( decl[index].Type == D3DDECLTYPE_SHORT4N ) - { - D3D11_INPUT_ELEMENT_DESC desc = elements[4]; - desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; - inputDesc.push_back( desc ); - offset += 8; - } - else if ( decl[index].Type == D3DDECLTYPE_UBYTE4N ) - { - D3D11_INPUT_ELEMENT_DESC desc = elements[4]; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - inputDesc.push_back( desc ); + enableSkinning = true; + inputDesc.push_back(elements[7]); offset += 4; } else break; } - else if ( decl[index].Usage == D3DDECLUSAGE_TEXCOORD ) - { - D3D11_INPUT_ELEMENT_DESC desc = elements[5]; - desc.SemanticIndex = decl[index].UsageIndex; - bool unk = false; - switch( decl[index].Type ) - { - case D3DDECLTYPE_FLOAT2: offset += 8; break; - case D3DDECLTYPE_FLOAT1: desc.Format = DXGI_FORMAT_R32_FLOAT; offset += 4; break; - case D3DDECLTYPE_FLOAT3: desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; offset += 12; break; - case D3DDECLTYPE_FLOAT4: desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; offset += 16; break; - case D3DDECLTYPE_FLOAT16_2: desc.Format = DXGI_FORMAT_R16G16_FLOAT; offset += 4; break; - case D3DDECLTYPE_FLOAT16_4: desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; offset += 8; break; - - default: - unk = true; - break; - } + if (!posfound) + throw std::exception("SV_Position is required"); - if ( unk ) - break; - - ++texcoords; - - inputDesc.push_back( desc ); - } - else if ( decl[index].Usage == D3DDECLUSAGE_BLENDINDICES && decl[index].Type == D3DDECLTYPE_UBYTE4 ) + if (texcoords == 2) { - enableSkinning = true; - inputDesc.push_back( elements[6] ); - offset += 4; + dualTexture = true; } - else if ( decl[index].Usage == D3DDECLUSAGE_BLENDWEIGHT && decl[index].Type == D3DDECLTYPE_UBYTE4N ) - { - enableSkinning = true; - inputDesc.push_back( elements[7] ); - offset += 4; - } - else - break; } - if ( !posfound ) - throw std::exception("SV_Position is required"); - - if ( texcoords == 2 ) + // Helper for creating a D3D input layout. + void CreateInputLayout(_In_ ID3D11Device* device, _In_ IEffect* effect, std::vector& inputDesc, _Out_ ID3D11InputLayout** pInputLayout) { - dualTexture = true; - } -} + void const* shaderByteCode; + size_t byteCodeLength; -// Helper for creating a D3D input layout. -static void CreateInputLayout(_In_ ID3D11Device* device, _In_ IEffect* effect, std::vector& inputDesc, _Out_ ID3D11InputLayout** pInputLayout) -{ - void const* shaderByteCode; - size_t byteCodeLength; - - effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); + effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); - ThrowIfFailed( - device->CreateInputLayout(inputDesc.data(), - static_cast( inputDesc.size() ), - shaderByteCode, byteCodeLength, - pInputLayout) - ); + ThrowIfFailed( + device->CreateInputLayout(inputDesc.data(), + static_cast(inputDesc.size()), + shaderByteCode, byteCodeLength, + pInputLayout) + ); - _Analysis_assume_(*pInputLayout != 0); + _Analysis_assume_(*pInputLayout != 0); - SetDebugObjectName(*pInputLayout, "ModelSDKMESH"); + SetDebugObjectName(*pInputLayout, "ModelSDKMESH"); + } } diff --git a/Kits/DirectXTK/Src/ModelLoadVBO.cpp b/Kits/DirectXTK/Src/ModelLoadVBO.cpp index c715f76d..64b1b888 100644 --- a/Kits/DirectXTK/Src/ModelLoadVBO.cpp +++ b/Kits/DirectXTK/Src/ModelLoadVBO.cpp @@ -21,51 +21,31 @@ #include "PlatformHelpers.h" #include "BinaryReader.h" +#include "vbo.h" + using namespace DirectX; using Microsoft::WRL::ComPtr; +static_assert(sizeof(VertexPositionNormalTexture) == 32, "VBO vertex size mismatch"); -//-------------------------------------------------------------------------------------- -// The VBO file format was introduced in the Windows 8.0 ResourceLoading sample. It's -// a simple binary file containing a 16-bit index buffer and a fixed-format vertex buffer. -// -// The meshconvert sample tool for DirectXMesh can produce this file type -// http://go.microsoft.com/fwlink/?LinkID=324981 -//-------------------------------------------------------------------------------------- - -namespace VBO +namespace { -#pragma pack(push,1) + //-------------------------------------------------------------------------------------- + // Shared VB input element description + INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; + std::shared_ptr> g_vbdecl; - struct header_t + BOOL CALLBACK InitializeDecl(PINIT_ONCE initOnce, PVOID Parameter, PVOID *lpContext) { - uint32_t numVertices; - uint32_t numIndices; - }; - -#pragma pack(pop) - -}; // namespace + UNREFERENCED_PARAMETER(initOnce); + UNREFERENCED_PARAMETER(Parameter); + UNREFERENCED_PARAMETER(lpContext); -static_assert(sizeof(VBO::header_t) == 8, "VBO header size mismatch"); -static_assert(sizeof(VertexPositionNormalTexture) == 32, "VBO vertex size mismatch"); - - -//-------------------------------------------------------------------------------------- -// Shared VB input element description -static INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; -static std::shared_ptr> g_vbdecl; + g_vbdecl = std::make_shared>(VertexPositionNormalTexture::InputElements, + VertexPositionNormalTexture::InputElements + VertexPositionNormalTexture::InputElementCount); -static BOOL CALLBACK InitializeDecl(PINIT_ONCE initOnce, PVOID Parameter, PVOID *lpContext) -{ - UNREFERENCED_PARAMETER(initOnce); - UNREFERENCED_PARAMETER(Parameter); - UNREFERENCED_PARAMETER(lpContext); - - g_vbdecl = std::make_shared>(VertexPositionNormalTexture::InputElements, - VertexPositionNormalTexture::InputElements + VertexPositionNormalTexture::InputElementCount); - - return TRUE; + return TRUE; + } } diff --git a/Kits/DirectXTK/Src/SDKMesh.h b/Kits/DirectXTK/Src/SDKMesh.h new file mode 100644 index 00000000..6848d9e5 --- /dev/null +++ b/Kits/DirectXTK/Src/SDKMesh.h @@ -0,0 +1,340 @@ +//-------------------------------------------------------------------------------------- +// File: SDKMesh.h +// +// SDKMESH format is generated by the legacy DirectX SDK's Content Exporter and +// originally rendered by the DXUT helper class SDKMesh +// +// http://go.microsoft.com/fwlink/?LinkId=226208 +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + + +namespace DXUT +{ + // .SDKMESH files + + // SDKMESH_HEADER + // SDKMESH_VERTEX_BUFFER_HEADER header->VertexStreamHeadersOffset + // SDKMESH_INDEX_BUFFER_HEADER header->IndexStreamHeadersOffset + // SDKMESH_MESH header->MeshDataOffset + // SDKMESH_SUBSET header->SubsetDataOffset + // SDKMESH_FRAME header->FrameDataOffset + // SDKMESH_MATERIAL header->MaterialDataOffset + // [header->NonBufferDataSize] + // { [ header->NumVertexBuffers] + // VB data + // } + // { [ header->NumIndexBuffers] + // IB data + // } + + + // .SDDKANIM files + + // SDKANIMATION_FILE_HEADER + // uint8_t[] - Length of fileheader->AnimationDataSize + + // .SDKMESH uses Direct3D 9 decls, but only a subset of these is ever generated by the legacy DirectX SDK Content Exporter + + // D3DDECLUSAGE_POSITION / D3DDECLTYPE_FLOAT3 + // (D3DDECLUSAGE_BLENDWEIGHT / D3DDECLTYPE_UBYTE4N + // D3DDECLUSAGE_BLENDINDICES / D3DDECLTYPE_UBYTE4)? + // (D3DDECLUSAGE_NORMAL / D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_UBYTE4N, or D3DDECLTYPE_DEC3N [not supported])? + // (D3DDECLUSAGE_COLOR / D3DDECLTYPE_D3DCOLOR)? + // (D3DDECLUSAGE_TEXCOORD / D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2 or D3DDECLTYPE_FLOAT16_2, D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_FLOAT4 or D3DDECLTYPE_FLOAT16_4)* + // (D3DDECLUSAGE_TANGENT / same as D3DDECLUSAGE_NORMAL)? + // (D3DDECLUSAGE_BINORMAL / same as D3DDECLUSAGE_NORMAL)? + + enum D3DDECLUSAGE + { + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT =1, + D3DDECLUSAGE_BLENDINDICES =2, + D3DDECLUSAGE_NORMAL =3, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_COLOR = 10, + }; + + enum D3DDECLTYPE + { + D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) + D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) + D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) + D3DDECLTYPE_FLOAT4 = 3, // 4D float + D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range + // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) + D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned uint8_t + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + // Note: There is no equivalent to D3DDECLTYPE_DEC3N (14) as a DXGI_FORMAT + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. + }; + + #pragma pack(push,4) + + struct D3DVERTEXELEMENT9 + { + uint16_t Stream; // Stream index + uint16_t Offset; // Offset in the stream in bytes + uint8_t Type; // Data type + uint8_t Method; // Processing method + uint8_t Usage; // Semantics + uint8_t UsageIndex; // Semantic index + }; + + #pragma pack(pop) + + //-------------------------------------------------------------------------------------- + // Hard Defines for the various structures + //-------------------------------------------------------------------------------------- + const uint32_t SDKMESH_FILE_VERSION = 101; + const uint32_t MAX_VERTEX_ELEMENTS = 32; + const uint32_t MAX_VERTEX_STREAMS = 16; + const uint32_t MAX_FRAME_NAME = 100; + const uint32_t MAX_MESH_NAME = 100; + const uint32_t MAX_SUBSET_NAME = 100; + const uint32_t MAX_MATERIAL_NAME = 100; + const uint32_t MAX_TEXTURE_NAME = MAX_PATH; + const uint32_t MAX_MATERIAL_PATH = MAX_PATH; + const uint32_t INVALID_FRAME = uint32_t(-1); + const uint32_t INVALID_MESH = uint32_t(-1); + const uint32_t INVALID_MATERIAL = uint32_t(-1); + const uint32_t INVALID_SUBSET = uint32_t(-1); + const uint32_t INVALID_ANIMATION_DATA = uint32_t(-1); + const uint32_t INVALID_SAMPLER_SLOT = uint32_t(-1); + const uint32_t ERROR_RESOURCE_VALUE = 1; + + //-------------------------------------------------------------------------------------- + // Enumerated Types. + //-------------------------------------------------------------------------------------- + enum SDKMESH_PRIMITIVE_TYPE + { + PT_TRIANGLE_LIST = 0, + PT_TRIANGLE_STRIP, + PT_LINE_LIST, + PT_LINE_STRIP, + PT_POINT_LIST, + PT_TRIANGLE_LIST_ADJ, + PT_TRIANGLE_STRIP_ADJ, + PT_LINE_LIST_ADJ, + PT_LINE_STRIP_ADJ, + PT_QUAD_PATCH_LIST, + PT_TRIANGLE_PATCH_LIST, + }; + + enum SDKMESH_INDEX_TYPE + { + IT_16BIT = 0, + IT_32BIT, + }; + + enum FRAME_TRANSFORM_TYPE + { + FTT_RELATIVE = 0, + FTT_ABSOLUTE, //This is not currently used but is here to support absolute transformations in the future + }; + + //-------------------------------------------------------------------------------------- + // Structures. + //-------------------------------------------------------------------------------------- + #pragma pack(push,8) + + struct SDKMESH_HEADER + { + //Basic Info and sizes + uint32_t Version; + uint8_t IsBigEndian; + uint64_t HeaderSize; + uint64_t NonBufferDataSize; + uint64_t BufferDataSize; + + //Stats + uint32_t NumVertexBuffers; + uint32_t NumIndexBuffers; + uint32_t NumMeshes; + uint32_t NumTotalSubsets; + uint32_t NumFrames; + uint32_t NumMaterials; + + //Offsets to Data + uint64_t VertexStreamHeadersOffset; + uint64_t IndexStreamHeadersOffset; + uint64_t MeshDataOffset; + uint64_t SubsetDataOffset; + uint64_t FrameDataOffset; + uint64_t MaterialDataOffset; + }; + + struct SDKMESH_VERTEX_BUFFER_HEADER + { + uint64_t NumVertices; + uint64_t SizeBytes; + uint64_t StrideBytes; + D3DVERTEXELEMENT9 Decl[MAX_VERTEX_ELEMENTS]; + union + { + uint64_t DataOffset; + }; + }; + + struct SDKMESH_INDEX_BUFFER_HEADER + { + uint64_t NumIndices; + uint64_t SizeBytes; + uint32_t IndexType; + union + { + uint64_t DataOffset; + }; + }; + + struct SDKMESH_MESH + { + char Name[MAX_MESH_NAME]; + uint8_t NumVertexBuffers; + uint32_t VertexBuffers[MAX_VERTEX_STREAMS]; + uint32_t IndexBuffer; + uint32_t NumSubsets; + uint32_t NumFrameInfluences; //aka bones + + DirectX::XMFLOAT3 BoundingBoxCenter; + DirectX::XMFLOAT3 BoundingBoxExtents; + + union + { + uint64_t SubsetOffset; + INT* pSubsets; + }; + union + { + uint64_t FrameInfluenceOffset; + uint32_t* pFrameInfluences; + }; + }; + + struct SDKMESH_SUBSET + { + char Name[MAX_SUBSET_NAME]; + uint32_t MaterialID; + uint32_t PrimitiveType; + uint64_t IndexStart; + uint64_t IndexCount; + uint64_t VertexStart; + uint64_t VertexCount; + }; + + struct SDKMESH_FRAME + { + char Name[MAX_FRAME_NAME]; + uint32_t Mesh; + uint32_t ParentFrame; + uint32_t ChildFrame; + uint32_t SiblingFrame; + DirectX::XMFLOAT4X4 Matrix; + uint32_t AnimationDataIndex; //Used to index which set of keyframes transforms this frame + }; + + struct SDKMESH_MATERIAL + { + char Name[MAX_MATERIAL_NAME]; + + // Use MaterialInstancePath + char MaterialInstancePath[MAX_MATERIAL_PATH]; + + // Or fall back to d3d8-type materials + char DiffuseTexture[MAX_TEXTURE_NAME]; + char NormalTexture[MAX_TEXTURE_NAME]; + char SpecularTexture[MAX_TEXTURE_NAME]; + + DirectX::XMFLOAT4 Diffuse; + DirectX::XMFLOAT4 Ambient; + DirectX::XMFLOAT4 Specular; + DirectX::XMFLOAT4 Emissive; + float Power; + + union + { + uint64_t Force64_1; //Force the union to 64bits + }; + union + { + uint64_t Force64_2; //Force the union to 64bits + }; + union + { + uint64_t Force64_3; //Force the union to 64bits + }; + + union + { + uint64_t Force64_4; //Force the union to 64bits + }; + union + { + uint64_t Force64_5; //Force the union to 64bits + }; + union + { + uint64_t Force64_6; //Force the union to 64bits + }; + }; + + struct SDKANIMATION_FILE_HEADER + { + uint32_t Version; + uint8_t IsBigEndian; + uint32_t FrameTransformType; + uint32_t NumFrames; + uint32_t NumAnimationKeys; + uint32_t AnimationFPS; + uint64_t AnimationDataSize; + uint64_t AnimationDataOffset; + }; + + struct SDKANIMATION_DATA + { + DirectX::XMFLOAT3 Translation; + DirectX::XMFLOAT4 Orientation; + DirectX::XMFLOAT3 Scaling; + }; + + struct SDKANIMATION_FRAME_DATA + { + char FrameName[MAX_FRAME_NAME]; + union + { + uint64_t DataOffset; + SDKANIMATION_DATA* pAnimationData; + }; + }; + + #pragma pack(pop) + +} // namespace + +static_assert( sizeof(DXUT::D3DVERTEXELEMENT9) == 8, "Direct3D9 Decl structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_HEADER)== 104, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) == 288, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER) == 32, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_MESH) == 224, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_SUBSET) == 144, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_FRAME) == 184, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_MATERIAL) == 1256, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_FILE_HEADER) == 40, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_DATA) == 40, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_FRAME_DATA) == 112, "SDK Mesh structure size incorrect" ); diff --git a/Kits/DirectXTK/Src/ScreenGrab.cpp b/Kits/DirectXTK/Src/ScreenGrab.cpp index 6fd542e5..5a59f60d 100644 --- a/Kits/DirectXTK/Src/ScreenGrab.cpp +++ b/Kits/DirectXTK/Src/ScreenGrab.cpp @@ -27,439 +27,18 @@ #include "pch.h" -#include - #include "ScreenGrab.h" #include "DirectXHelpers.h" #include "dds.h" #include "PlatformHelpers.h" +#include "LoaderHelpers.h" using Microsoft::WRL::ComPtr; using namespace DirectX; namespace { - class auto_delete_file - { - public: - auto_delete_file(HANDLE hFile) : m_handle(hFile) {} - - auto_delete_file(const auto_delete_file&) = delete; - auto_delete_file& operator=(const auto_delete_file&) = delete; - - ~auto_delete_file() - { - if (m_handle) - { - FILE_DISPOSITION_INFO info = {}; - info.DeleteFile = TRUE; - (void)SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, sizeof(info)); - } - } - - void clear() { m_handle = 0; } - - private: - HANDLE m_handle; - }; - - class auto_delete_file_wic - { - public: - auto_delete_file_wic(ComPtr& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {} - - auto_delete_file_wic(const auto_delete_file_wic&) = delete; - auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete; - - ~auto_delete_file_wic() - { - if (m_filename) - { - m_handle.Reset(); - DeleteFileW(m_filename); - } - } - - void clear() { m_filename = 0; } - - private: - LPCWSTR m_filename; - ComPtr& m_handle; - }; - - //-------------------------------------------------------------------------------------- - // Return the BPP for a particular format - //-------------------------------------------------------------------------------------- - size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) - { - switch (fmt) - { - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_UINT: - case DXGI_FORMAT_R32G32B32A32_SINT: - return 128; - - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_UINT: - case DXGI_FORMAT_R32G32B32_SINT: - return 96; - - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - case DXGI_FORMAT_Y416: - case DXGI_FORMAT_Y210: - case DXGI_FORMAT_Y216: - return 64; - - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_AYUV: - case DXGI_FORMAT_Y410: - case DXGI_FORMAT_YUY2: - return 32; - - case DXGI_FORMAT_P010: - case DXGI_FORMAT_P016: - return 24; - - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_A8P8: - case DXGI_FORMAT_B4G4R4A4_UNORM: - return 16; - - case DXGI_FORMAT_NV12: - case DXGI_FORMAT_420_OPAQUE: - case DXGI_FORMAT_NV11: - return 12; - - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_AI44: - case DXGI_FORMAT_IA44: - case DXGI_FORMAT_P8: - return 8; - - case DXGI_FORMAT_R1_UNORM: - return 1; - - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - return 4; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - -#if defined(_XBOX_ONE) && defined(_TITLE) - - case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: - case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: - case DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: - return 32; - - case DXGI_FORMAT_D16_UNORM_S8_UINT: - case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X16_TYPELESS_G8_UINT: - return 24; - - case DXGI_FORMAT_R4G4_UNORM: - return 8; - -#endif // _XBOX_ONE && _TITLE - - default: - return 0; - } - } - - //-------------------------------------------------------------------------------------- - // Determines if the format is block compressed - //-------------------------------------------------------------------------------------- - bool IsCompressed(_In_ DXGI_FORMAT fmt) - { - switch (fmt) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return true; - - default: - return false; - } - } - - //-------------------------------------------------------------------------------------- - // Get surface information for a particular format - //-------------------------------------------------------------------------------------- - void GetSurfaceInfo(_In_ size_t width, - _In_ size_t height, - _In_ DXGI_FORMAT fmt, - _Out_opt_ size_t* outNumBytes, - _Out_opt_ size_t* outRowBytes, - _Out_opt_ size_t* outNumRows) - { - size_t numBytes = 0; - size_t rowBytes = 0; - size_t numRows = 0; - - bool bc = false; - bool packed = false; - bool planar = false; - size_t bpe = 0; - switch (fmt) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - bc = true; - bpe = 8; - break; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - bc = true; - bpe = 16; - break; - - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_YUY2: - packed = true; - bpe = 4; - break; - - case DXGI_FORMAT_Y210: - case DXGI_FORMAT_Y216: - packed = true; - bpe = 8; - break; - - case DXGI_FORMAT_NV12: - case DXGI_FORMAT_420_OPAQUE: - planar = true; - bpe = 2; - break; - - case DXGI_FORMAT_P010: - case DXGI_FORMAT_P016: - planar = true; - bpe = 4; - break; - -#if defined(_XBOX_ONE) && defined(_TITLE) - - case DXGI_FORMAT_D16_UNORM_S8_UINT: - case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X16_TYPELESS_G8_UINT: - planar = true; - bpe = 4; - break; - -#endif - } - - if (bc) - { - size_t numBlocksWide = 0; - if (width > 0) - { - numBlocksWide = std::max(1, (width + 3) / 4); - } - size_t numBlocksHigh = 0; - if (height > 0) - { - numBlocksHigh = std::max(1, (height + 3) / 4); - } - rowBytes = numBlocksWide * bpe; - numRows = numBlocksHigh; - numBytes = rowBytes * numBlocksHigh; - } - else if (packed) - { - rowBytes = ((width + 1) >> 1) * bpe; - numRows = height; - numBytes = rowBytes * height; - } - else if (fmt == DXGI_FORMAT_NV11) - { - rowBytes = ((width + 3) >> 2) * 4; - numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data - numBytes = rowBytes * numRows; - } - else if (planar) - { - rowBytes = ((width + 1) >> 1) * bpe; - numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1); - numRows = height + ((height + 1) >> 1); - } - else - { - size_t bpp = BitsPerPixel(fmt); - rowBytes = (width * bpp + 7) / 8; // round up to nearest byte - numRows = height; - numBytes = rowBytes * height; - } - - if (outNumBytes) - { - *outNumBytes = numBytes; - } - if (outRowBytes) - { - *outRowBytes = rowBytes; - } - if (outNumRows) - { - *outNumRows = numRows; - } - } - - //-------------------------------------------------------------------------------------- - DXGI_FORMAT EnsureNotTypeless(DXGI_FORMAT fmt) - { - // Assumes UNORM or FLOAT; doesn't use UINT or SINT - switch (fmt) - { - case DXGI_FORMAT_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_FLOAT; - case DXGI_FORMAT_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_FLOAT; - case DXGI_FORMAT_R16G16B16A16_TYPELESS: return DXGI_FORMAT_R16G16B16A16_UNORM; - case DXGI_FORMAT_R32G32_TYPELESS: return DXGI_FORMAT_R32G32_FLOAT; - case DXGI_FORMAT_R10G10B10A2_TYPELESS: return DXGI_FORMAT_R10G10B10A2_UNORM; - case DXGI_FORMAT_R8G8B8A8_TYPELESS: return DXGI_FORMAT_R8G8B8A8_UNORM; - case DXGI_FORMAT_R16G16_TYPELESS: return DXGI_FORMAT_R16G16_UNORM; - case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_R32_FLOAT; - case DXGI_FORMAT_R8G8_TYPELESS: return DXGI_FORMAT_R8G8_UNORM; - case DXGI_FORMAT_R16_TYPELESS: return DXGI_FORMAT_R16_UNORM; - case DXGI_FORMAT_R8_TYPELESS: return DXGI_FORMAT_R8_UNORM; - case DXGI_FORMAT_BC1_TYPELESS: return DXGI_FORMAT_BC1_UNORM; - case DXGI_FORMAT_BC2_TYPELESS: return DXGI_FORMAT_BC2_UNORM; - case DXGI_FORMAT_BC3_TYPELESS: return DXGI_FORMAT_BC3_UNORM; - case DXGI_FORMAT_BC4_TYPELESS: return DXGI_FORMAT_BC4_UNORM; - case DXGI_FORMAT_BC5_TYPELESS: return DXGI_FORMAT_BC5_UNORM; - case DXGI_FORMAT_B8G8R8A8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_UNORM; - case DXGI_FORMAT_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8X8_UNORM; - case DXGI_FORMAT_BC7_TYPELESS: return DXGI_FORMAT_BC7_UNORM; - default: return fmt; - } - } - //-------------------------------------------------------------------------------------- HRESULT CaptureTexture(_In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, @@ -584,9 +163,10 @@ namespace //-------------------------------------------------------------------------------------- -HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext, - _In_ ID3D11Resource* pSource, - _In_z_ LPCWSTR fileName ) +_Use_decl_annotations_ +HRESULT DirectX::SaveDDSTextureToFile( ID3D11DeviceContext* pContext, + ID3D11Resource* pSource, + const wchar_t* fileName ) { if ( !fileName ) return E_INVALIDARG; @@ -750,12 +330,13 @@ extern bool _IsWIC2(); extern IWICImagingFactory* _GetWIC(); } -HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext, - _In_ ID3D11Resource* pSource, - _In_ REFGUID guidContainerFormat, - _In_z_ LPCWSTR fileName, - _In_opt_ const GUID* targetFormat, - _In_opt_ std::function setCustomProps ) +_Use_decl_annotations_ +HRESULT DirectX::SaveWICTextureToFile( ID3D11DeviceContext* pContext, + ID3D11Resource* pSource, + REFGUID guidContainerFormat, + const wchar_t* fileName, + const GUID* targetFormat, + std::function setCustomProps ) { if ( !fileName ) return E_INVALIDARG; diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc index e4e49e9b..52665d85 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc @@ -41,7 +41,7 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 115 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 115 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" texld r0, t2, s0 mad r1.w, r0.w, t0.w, -c0.x mul r0, r0, t0 // ::color<0,1,2,3> @@ -50,7 +50,7 @@ cmp r1, r1.x, c0.w, c0.z texkill r1 -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, c1, r0.w, -r0 mad r0.xyz, t1.w, r1, r0 // ApplyFog::color<0,1,2> mov oC0, r0 // ::PSAlphaTestEqNe<0,1,2,3> @@ -81,17 +81,17 @@ ret const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = { - 68, 88, 66, 67, 208, 75, - 162, 32, 33, 200, 11, 204, - 50, 168, 64, 242, 244, 89, - 11, 137, 1, 0, 0, 0, - 56, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 213, 22, + 225, 159, 196, 224, 154, 245, + 216, 172, 86, 60, 68, 240, + 161, 5, 1, 0, 0, 0, + 68, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 220, 3, 0, 0, 156, 5, - 0, 0, 4, 6, 0, 0, - 65, 111, 110, 57, 164, 3, - 0, 0, 164, 3, 0, 0, - 0, 2, 255, 255, 112, 3, + 232, 3, 0, 0, 168, 5, + 0, 0, 16, 6, 0, 0, + 65, 111, 110, 57, 176, 3, + 0, 0, 176, 3, 0, 0, + 0, 2, 255, 255, 124, 3, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -100,14 +100,14 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 165, 0, 68, 66, 85, 71, + 168, 0, 68, 66, 85, 71, 40, 0, 0, 0, 104, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 14, 0, 0, 0, 200, 0, 0, 0, 4, 0, 0, 0, 24, 2, 0, 0, - 56, 1, 0, 0, 67, 58, + 56, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -120,7 +120,7 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = 101, 114, 115, 92, 65, 108, 112, 104, 97, 84, 101, 115, 116, 69, 102, 102, 101, 99, - 116, 46, 102, 120, 0, 67, + 116, 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -135,24 +135,24 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = 102, 120, 104, 0, 171, 171, 40, 0, 0, 0, 119, 0, 0, 0, 0, 0, 255, 255, - 156, 2, 0, 0, 0, 0, - 255, 255, 168, 2, 0, 0, - 0, 0, 255, 255, 180, 2, + 168, 2, 0, 0, 0, 0, + 255, 255, 180, 2, 0, 0, + 0, 0, 255, 255, 192, 2, 0, 0, 0, 0, 255, 255, - 192, 2, 0, 0, 115, 0, - 0, 0, 204, 2, 0, 0, - 117, 0, 0, 0, 220, 2, + 204, 2, 0, 0, 115, 0, + 0, 0, 216, 2, 0, 0, + 117, 0, 0, 0, 232, 2, 0, 0, 115, 0, 0, 0, - 240, 2, 0, 0, 117, 0, - 0, 0, 0, 3, 0, 0, - 117, 0, 0, 0, 12, 3, + 252, 2, 0, 0, 117, 0, + 0, 0, 12, 3, 0, 0, + 117, 0, 0, 0, 24, 3, 0, 0, 117, 0, 0, 0, - 28, 3, 0, 0, 117, 0, - 0, 0, 48, 3, 0, 0, - 20, 0, 1, 0, 56, 3, + 40, 3, 0, 0, 117, 0, + 0, 0, 60, 3, 0, 0, + 20, 0, 1, 0, 68, 3, 0, 0, 20, 0, 1, 0, - 76, 3, 0, 0, 20, 0, - 1, 0, 96, 3, 0, 0, + 88, 3, 0, 0, 20, 0, + 1, 0, 108, 3, 0, 0, 80, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 69, 113, 78, 101, 0, 1, 0, @@ -210,7 +210,9 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc index df910cd7..cbe52baf 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc @@ -39,7 +39,7 @@ dcl t1.xy // pin<4,5> dcl_2d s0 -#line 128 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 128 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" texld r0, t1, s0 mad r1.w, r0.w, t0.w, -c0.x mul r0, r0, t0 // ::color<0,1,2,3> @@ -72,17 +72,17 @@ ret const BYTE AlphaTestEffect_PSAlphaTestEqNeNoFog[] = { - 68, 88, 66, 67, 207, 117, - 57, 224, 226, 104, 212, 180, - 83, 188, 48, 87, 162, 23, - 138, 157, 1, 0, 0, 0, - 240, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 157, 210, + 136, 20, 124, 194, 207, 200, + 252, 104, 169, 73, 17, 89, + 40, 125, 1, 0, 0, 0, + 252, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 8, 3, 0, 0, 108, 4, - 0, 0, 188, 4, 0, 0, - 65, 111, 110, 57, 208, 2, - 0, 0, 208, 2, 0, 0, - 0, 2, 255, 255, 156, 2, + 20, 3, 0, 0, 120, 4, + 0, 0, 200, 4, 0, 0, + 65, 111, 110, 57, 220, 2, + 0, 0, 220, 2, 0, 0, + 0, 2, 255, 255, 168, 2, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -91,14 +91,14 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNeNoFog[] = 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 125, 0, 68, 66, 85, 71, + 128, 0, 68, 66, 85, 71, 40, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0, 0, 11, 0, 0, 0, 124, 0, 0, 0, 3, 0, 0, 0, 140, 1, 0, 0, - 212, 0, 0, 0, 67, 58, + 212, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -113,20 +113,20 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNeNoFog[] = 116, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 252, 1, 0, 0, - 0, 0, 255, 255, 8, 2, + 255, 255, 8, 2, 0, 0, + 0, 0, 255, 255, 20, 2, 0, 0, 0, 0, 255, 255, - 20, 2, 0, 0, 128, 0, - 0, 0, 32, 2, 0, 0, - 130, 0, 0, 0, 48, 2, + 32, 2, 0, 0, 128, 0, + 0, 0, 44, 2, 0, 0, + 130, 0, 0, 0, 60, 2, 0, 0, 128, 0, 0, 0, - 68, 2, 0, 0, 128, 0, - 0, 0, 84, 2, 0, 0, - 130, 0, 0, 0, 96, 2, + 80, 2, 0, 0, 128, 0, + 0, 0, 96, 2, 0, 0, + 130, 0, 0, 0, 108, 2, 0, 0, 130, 0, 0, 0, - 108, 2, 0, 0, 130, 0, - 0, 0, 124, 2, 0, 0, - 130, 0, 0, 0, 144, 2, + 120, 2, 0, 0, 130, 0, + 0, 0, 136, 2, 0, 0, + 130, 0, 0, 0, 156, 2, 0, 0, 80, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 69, 113, 78, 101, 78, @@ -174,7 +174,9 @@ const BYTE AlphaTestEffect_PSAlphaTestEqNeNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc index 4791ffff..b78c7141 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc @@ -41,14 +41,14 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 91 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 91 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" texld r0, t2, s0 mad r1.w, r0.w, t0.w, -c0.x mul r0, r0, t0 // ::color<0,1,2,3> cmp r1, r1.w, c0.w, c0.z texkill r1 -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, c1, r0.w, -r0 mad r0.xyz, t1.w, r1, r0 // ApplyFog::color<0,1,2> mov oC0, r0 // ::PSAlphaTestLtGt<0,1,2,3> @@ -78,17 +78,17 @@ ret const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = { - 68, 88, 66, 67, 241, 64, - 251, 39, 121, 132, 229, 238, - 105, 177, 37, 183, 88, 131, - 121, 143, 1, 0, 0, 0, - 220, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 7, 91, + 41, 243, 41, 36, 62, 189, + 3, 122, 247, 148, 151, 220, + 247, 123, 1, 0, 0, 0, + 232, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 176, 3, 0, 0, 64, 5, - 0, 0, 168, 5, 0, 0, - 65, 111, 110, 57, 120, 3, - 0, 0, 120, 3, 0, 0, - 0, 2, 255, 255, 68, 3, + 188, 3, 0, 0, 76, 5, + 0, 0, 180, 5, 0, 0, + 65, 111, 110, 57, 132, 3, + 0, 0, 132, 3, 0, 0, + 0, 2, 255, 255, 80, 3, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -97,14 +97,14 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 161, 0, 68, 66, 85, 71, + 164, 0, 68, 66, 85, 71, 40, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 12, 0, 0, 0, 200, 0, 0, 0, 4, 0, 0, 0, 8, 2, 0, 0, - 40, 1, 0, 0, 67, 58, + 40, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -117,7 +117,7 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = 101, 114, 115, 92, 65, 108, 112, 104, 97, 84, 101, 115, 116, 69, 102, 102, 101, 99, - 116, 46, 102, 120, 0, 67, + 116, 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -132,21 +132,21 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = 102, 120, 104, 0, 171, 171, 40, 0, 0, 0, 119, 0, 0, 0, 0, 0, 255, 255, - 140, 2, 0, 0, 0, 0, - 255, 255, 152, 2, 0, 0, - 0, 0, 255, 255, 164, 2, + 152, 2, 0, 0, 0, 0, + 255, 255, 164, 2, 0, 0, + 0, 0, 255, 255, 176, 2, 0, 0, 0, 0, 255, 255, - 176, 2, 0, 0, 91, 0, - 0, 0, 188, 2, 0, 0, - 93, 0, 0, 0, 204, 2, + 188, 2, 0, 0, 91, 0, + 0, 0, 200, 2, 0, 0, + 93, 0, 0, 0, 216, 2, 0, 0, 91, 0, 0, 0, - 224, 2, 0, 0, 93, 0, - 0, 0, 240, 2, 0, 0, - 93, 0, 0, 0, 4, 3, + 236, 2, 0, 0, 93, 0, + 0, 0, 252, 2, 0, 0, + 93, 0, 0, 0, 16, 3, 0, 0, 20, 0, 1, 0, - 12, 3, 0, 0, 20, 0, - 1, 0, 32, 3, 0, 0, - 20, 0, 1, 0, 52, 3, + 24, 3, 0, 0, 20, 0, + 1, 0, 44, 3, 0, 0, + 20, 0, 1, 0, 64, 3, 0, 0, 80, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 76, 116, 71, 116, 0, @@ -204,7 +204,9 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc index 31637370..9c4e780e 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc @@ -39,7 +39,7 @@ dcl t1.xy // pin<4,5> dcl_2d s0 -#line 104 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 104 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" texld r0, t1, s0 mad r1.w, r0.w, t0.w, -c0.x mul r0, r0, t0 // ::color<0,1,2,3> @@ -69,17 +69,17 @@ ret const BYTE AlphaTestEffect_PSAlphaTestLtGtNoFog[] = { - 68, 88, 66, 67, 156, 146, - 229, 145, 172, 111, 60, 108, - 100, 90, 170, 220, 44, 19, - 147, 95, 1, 0, 0, 0, - 148, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 200, 27, + 254, 82, 190, 48, 231, 23, + 72, 151, 74, 62, 109, 178, + 190, 75, 1, 0, 0, 0, + 160, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 220, 2, 0, 0, 16, 4, - 0, 0, 96, 4, 0, 0, - 65, 111, 110, 57, 164, 2, - 0, 0, 164, 2, 0, 0, - 0, 2, 255, 255, 112, 2, + 232, 2, 0, 0, 28, 4, + 0, 0, 108, 4, 0, 0, + 65, 111, 110, 57, 176, 2, + 0, 0, 176, 2, 0, 0, + 0, 2, 255, 255, 124, 2, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -88,14 +88,14 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGtNoFog[] = 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 121, 0, 68, 66, 85, 71, + 124, 0, 68, 66, 85, 71, 40, 0, 0, 0, 184, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0, 0, 9, 0, 0, 0, 124, 0, 0, 0, 3, 0, 0, 0, 124, 1, 0, 0, - 196, 0, 0, 0, 67, 58, + 196, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -110,18 +110,18 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGtNoFog[] = 116, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 236, 1, 0, 0, - 0, 0, 255, 255, 248, 1, + 255, 255, 248, 1, 0, 0, + 0, 0, 255, 255, 4, 2, 0, 0, 0, 0, 255, 255, - 4, 2, 0, 0, 104, 0, - 0, 0, 16, 2, 0, 0, - 106, 0, 0, 0, 32, 2, + 16, 2, 0, 0, 104, 0, + 0, 0, 28, 2, 0, 0, + 106, 0, 0, 0, 44, 2, 0, 0, 104, 0, 0, 0, - 52, 2, 0, 0, 104, 0, - 0, 0, 68, 2, 0, 0, - 106, 0, 0, 0, 80, 2, + 64, 2, 0, 0, 104, 0, + 0, 0, 80, 2, 0, 0, + 106, 0, 0, 0, 92, 2, 0, 0, 106, 0, 0, 0, - 100, 2, 0, 0, 80, 83, + 112, 2, 0, 0, 80, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 76, 116, 71, 116, 78, 111, 70, 111, 103, @@ -168,7 +168,9 @@ const BYTE AlphaTestEffect_PSAlphaTestLtGtNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc index bb81399d..51e8b96d 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc @@ -43,7 +43,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSAlphaTest<12> #line 14 @@ -56,15 +56,15 @@ dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 31 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 31 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSAlphaTest<10,11> mov oPos.w, r0.z // ::VSAlphaTest<13> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSAlphaTest<0,1,2,3> mov oT1.xyz, c7.x // ::VSAlphaTest<4,5,6> -#line 38 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 38 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mov oT2.xy, v1 // ::VSAlphaTest<8,9> // approximately 12 instruction slots used @@ -90,17 +90,17 @@ ret const BYTE AlphaTestEffect_VSAlphaTest[] = { - 68, 88, 66, 67, 140, 250, - 248, 103, 246, 98, 11, 172, - 23, 163, 14, 30, 10, 157, - 29, 143, 1, 0, 0, 0, - 252, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 215, 191, + 220, 167, 117, 124, 197, 150, + 220, 90, 78, 96, 232, 251, + 248, 211, 1, 0, 0, 0, + 8, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 188, 4, 0, 0, 24, 6, - 0, 0, 112, 6, 0, 0, - 65, 111, 110, 57, 132, 4, - 0, 0, 132, 4, 0, 0, - 0, 2, 254, 255, 68, 4, + 200, 4, 0, 0, 36, 6, + 0, 0, 124, 6, 0, 0, + 65, 111, 110, 57, 144, 4, + 0, 0, 144, 4, 0, 0, + 0, 2, 254, 255, 80, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -111,14 +111,14 @@ const BYTE AlphaTestEffect_VSAlphaTest[] = 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 213, 0, 68, 66, 85, 71, + 216, 0, 68, 66, 85, 71, 40, 0, 0, 0, 40, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 236, 2, 0, 0, - 64, 1, 0, 0, 67, 58, + 64, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -130,7 +130,7 @@ const BYTE AlphaTestEffect_VSAlphaTest[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -146,25 +146,25 @@ const BYTE AlphaTestEffect_VSAlphaTest[] = 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 92, 3, 0, 0, 0, 0, - 255, 255, 116, 3, 0, 0, - 0, 0, 255, 255, 128, 3, + 104, 3, 0, 0, 0, 0, + 255, 255, 128, 3, 0, 0, + 0, 0, 255, 255, 140, 3, 0, 0, 43, 0, 0, 0, - 140, 3, 0, 0, 14, 0, - 0, 0, 156, 3, 0, 0, - 14, 0, 0, 0, 172, 3, + 152, 3, 0, 0, 14, 0, + 0, 0, 168, 3, 0, 0, + 14, 0, 0, 0, 184, 3, 0, 0, 14, 0, 0, 0, - 188, 3, 0, 0, 43, 0, - 0, 0, 204, 3, 0, 0, - 43, 0, 0, 0, 220, 3, + 200, 3, 0, 0, 43, 0, + 0, 0, 216, 3, 0, 0, + 43, 0, 0, 0, 232, 3, 0, 0, 43, 0, 0, 0, - 236, 3, 0, 0, 31, 0, - 1, 0, 252, 3, 0, 0, - 31, 0, 1, 0, 16, 4, + 248, 3, 0, 0, 31, 0, + 1, 0, 8, 4, 0, 0, + 31, 0, 1, 0, 28, 4, 0, 0, 44, 0, 0, 0, - 28, 4, 0, 0, 45, 0, - 0, 0, 40, 4, 0, 0, - 38, 0, 1, 0, 52, 4, + 40, 4, 0, 0, 45, 0, + 0, 0, 52, 4, 0, 0, + 38, 0, 1, 0, 64, 4, 0, 0, 86, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 0, 68, 105, 102, 102, @@ -253,7 +253,9 @@ const BYTE AlphaTestEffect_VSAlphaTest[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc index 7687d134..751786f1 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc @@ -41,20 +41,20 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSAlphaTestNoFog<8> dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 45 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 45 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSAlphaTestNoFog<6,7> mov oPos.w, r0.z // ::VSAlphaTestNoFog<9> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSAlphaTestNoFog<0,1,2,3> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mov oT1.xy, v1 // ::VSAlphaTestNoFog<4,5> // approximately 8 instruction slots used @@ -77,17 +77,17 @@ ret const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = { - 68, 88, 66, 67, 248, 2, - 209, 10, 206, 132, 220, 115, - 131, 91, 104, 83, 66, 167, - 100, 45, 1, 0, 0, 0, - 8, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 11, 181, + 82, 81, 226, 16, 97, 224, + 184, 138, 56, 134, 96, 133, + 166, 216, 1, 0, 0, 0, + 20, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 44, 4, 0, 0, 60, 5, - 0, 0, 148, 5, 0, 0, - 65, 111, 110, 57, 244, 3, - 0, 0, 244, 3, 0, 0, - 0, 2, 254, 255, 180, 3, + 56, 4, 0, 0, 72, 5, + 0, 0, 160, 5, 0, 0, + 65, 111, 110, 57, 0, 4, + 0, 0, 0, 4, 0, 0, + 0, 2, 254, 255, 192, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -98,14 +98,14 @@ const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 198, 0, 68, 66, 85, 71, + 201, 0, 68, 66, 85, 71, 40, 0, 0, 0, 236, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 10, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 176, 2, 0, 0, - 24, 1, 0, 0, 67, 58, + 24, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -117,7 +117,7 @@ const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -133,19 +133,19 @@ const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 32, 3, 0, 0, 0, 0, - 255, 255, 44, 3, 0, 0, - 43, 0, 0, 0, 56, 3, + 44, 3, 0, 0, 0, 0, + 255, 255, 56, 3, 0, 0, + 43, 0, 0, 0, 68, 3, 0, 0, 43, 0, 0, 0, - 72, 3, 0, 0, 43, 0, - 0, 0, 88, 3, 0, 0, - 43, 0, 0, 0, 104, 3, + 84, 3, 0, 0, 43, 0, + 0, 0, 100, 3, 0, 0, + 43, 0, 0, 0, 116, 3, 0, 0, 45, 0, 1, 0, - 120, 3, 0, 0, 45, 0, - 1, 0, 140, 3, 0, 0, - 44, 0, 0, 0, 152, 3, + 132, 3, 0, 0, 45, 0, + 1, 0, 152, 3, 0, 0, + 44, 0, 0, 0, 164, 3, 0, 0, 52, 0, 1, 0, - 164, 3, 0, 0, 86, 83, + 176, 3, 0, 0, 86, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 78, 111, 70, 111, 103, 0, 68, 105, 102, @@ -230,7 +230,9 @@ const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc index ad33aa9c..0c709a7c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc @@ -45,7 +45,7 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7,8,9> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSAlphaTestVc<12> #line 14 @@ -53,22 +53,22 @@ max r0.x, r0.x, c7.x min oT1.w, r0.x, c7.y // ::VSAlphaTestVc<7> -#line 67 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 67 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mul oT0, v2, c1 // ::VSAlphaTestVc<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c3 // ::vout<0> dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSAlphaTestVc<10,11> mov oPos.w, r0.z // ::VSAlphaTestVc<13> -#line 45 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 45 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT1.xyz, c7.x // ::VSAlphaTestVc<4,5,6> -#line 66 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 66 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mov oT2.xy, v1 // ::VSAlphaTestVc<8,9> // approximately 12 instruction slots used @@ -95,17 +95,17 @@ ret const BYTE AlphaTestEffect_VSAlphaTestVc[] = { - 68, 88, 66, 67, 84, 82, - 52, 236, 254, 37, 130, 12, - 230, 48, 204, 9, 82, 225, - 210, 117, 1, 0, 0, 0, - 96, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 216, 33, + 230, 173, 148, 214, 70, 100, + 18, 157, 32, 82, 49, 118, + 112, 169, 1, 0, 0, 0, + 108, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 240, 4, 0, 0, 96, 6, - 0, 0, 212, 6, 0, 0, - 65, 111, 110, 57, 184, 4, - 0, 0, 184, 4, 0, 0, - 0, 2, 254, 255, 120, 4, + 252, 4, 0, 0, 108, 6, + 0, 0, 224, 6, 0, 0, + 65, 111, 110, 57, 196, 4, + 0, 0, 196, 4, 0, 0, + 0, 2, 254, 255, 132, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -116,14 +116,14 @@ const BYTE AlphaTestEffect_VSAlphaTestVc[] = 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 222, 0, 68, 66, 85, 71, + 225, 0, 68, 66, 85, 71, 40, 0, 0, 0, 76, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 16, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 16, 3, 0, 0, - 72, 1, 0, 0, 67, 58, + 72, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -135,7 +135,7 @@ const BYTE AlphaTestEffect_VSAlphaTestVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -151,27 +151,27 @@ const BYTE AlphaTestEffect_VSAlphaTestVc[] = 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 128, 3, 0, 0, 0, 0, - 255, 255, 152, 3, 0, 0, - 0, 0, 255, 255, 164, 3, + 140, 3, 0, 0, 0, 0, + 255, 255, 164, 3, 0, 0, + 0, 0, 255, 255, 176, 3, 0, 0, 0, 0, 255, 255, - 176, 3, 0, 0, 43, 0, - 0, 0, 188, 3, 0, 0, - 14, 0, 0, 0, 204, 3, + 188, 3, 0, 0, 43, 0, + 0, 0, 200, 3, 0, 0, + 14, 0, 0, 0, 216, 3, 0, 0, 14, 0, 0, 0, - 220, 3, 0, 0, 14, 0, - 0, 0, 236, 3, 0, 0, - 67, 0, 1, 0, 252, 3, + 232, 3, 0, 0, 14, 0, + 0, 0, 248, 3, 0, 0, + 67, 0, 1, 0, 8, 4, 0, 0, 43, 0, 0, 0, - 12, 4, 0, 0, 43, 0, - 0, 0, 28, 4, 0, 0, - 43, 0, 0, 0, 44, 4, + 24, 4, 0, 0, 43, 0, + 0, 0, 40, 4, 0, 0, + 43, 0, 0, 0, 56, 4, 0, 0, 59, 0, 1, 0, - 60, 4, 0, 0, 59, 0, - 1, 0, 80, 4, 0, 0, - 45, 0, 0, 0, 92, 4, + 72, 4, 0, 0, 59, 0, + 1, 0, 92, 4, 0, 0, + 45, 0, 0, 0, 104, 4, 0, 0, 66, 0, 1, 0, - 104, 4, 0, 0, 86, 83, + 116, 4, 0, 0, 86, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 86, 99, 0, 68, 105, 102, 102, 117, 115, @@ -264,7 +264,9 @@ const BYTE AlphaTestEffect_VSAlphaTestVc[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc index ac487f1c..4a02ab83 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc @@ -43,18 +43,18 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7,8,9> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSAlphaTestVcNoFog<8> -#line 82 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 82 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mul oT0, v2, c1 // ::VSAlphaTestVcNoFog<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 74 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" +#line 74 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\AlphaTestEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSAlphaTestVcNoFog<6,7> mov oPos.w, r0.z // ::VSAlphaTestVcNoFog<9> @@ -82,17 +82,17 @@ ret const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = { - 68, 88, 66, 67, 74, 170, - 254, 68, 17, 213, 142, 220, - 24, 197, 43, 129, 118, 164, - 64, 53, 1, 0, 0, 0, - 104, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 177, 99, + 97, 235, 29, 185, 115, 88, + 142, 120, 132, 193, 103, 232, + 223, 216, 1, 0, 0, 0, + 116, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 92, 4, 0, 0, 128, 5, - 0, 0, 244, 5, 0, 0, - 65, 111, 110, 57, 36, 4, - 0, 0, 36, 4, 0, 0, - 0, 2, 254, 255, 228, 3, + 104, 4, 0, 0, 140, 5, + 0, 0, 0, 6, 0, 0, + 65, 111, 110, 57, 48, 4, + 0, 0, 48, 4, 0, 0, + 0, 2, 254, 255, 240, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -103,14 +103,14 @@ const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 206, 0, 68, 66, 85, 71, + 209, 0, 68, 66, 85, 71, 40, 0, 0, 0, 12, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 11, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 208, 2, 0, 0, - 32, 1, 0, 0, 67, 58, + 32, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -122,7 +122,7 @@ const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -138,20 +138,20 @@ const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 64, 3, 0, 0, 0, 0, - 255, 255, 76, 3, 0, 0, - 0, 0, 255, 255, 88, 3, + 76, 3, 0, 0, 0, 0, + 255, 255, 88, 3, 0, 0, + 0, 0, 255, 255, 100, 3, 0, 0, 43, 0, 0, 0, - 100, 3, 0, 0, 82, 0, - 1, 0, 116, 3, 0, 0, - 43, 0, 0, 0, 132, 3, + 112, 3, 0, 0, 82, 0, + 1, 0, 128, 3, 0, 0, + 43, 0, 0, 0, 144, 3, 0, 0, 43, 0, 0, 0, - 148, 3, 0, 0, 43, 0, - 0, 0, 164, 3, 0, 0, - 74, 0, 1, 0, 180, 3, + 160, 3, 0, 0, 43, 0, + 0, 0, 176, 3, 0, 0, + 74, 0, 1, 0, 192, 3, 0, 0, 74, 0, 1, 0, - 200, 3, 0, 0, 81, 0, - 1, 0, 212, 3, 0, 0, + 212, 3, 0, 0, 81, 0, + 1, 0, 224, 3, 0, 0, 86, 83, 65, 108, 112, 104, 97, 84, 101, 115, 116, 86, 99, 78, 111, 70, 111, 103, @@ -240,7 +240,9 @@ const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasic.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasic.inc index 9fbb00ea..a6b9612a 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasic.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasic.inc @@ -31,7 +31,7 @@ dcl t0 // pin<0,1,2,3> dcl t1 // pin<4,5,6,7> -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r0.xyz, c0, t0.w, -t0 mov r1.xyz, t0 // pin<0,1,2> mad r0.xyz, t1.w, r0, r1 // ApplyFog::color<0,1,2> @@ -54,17 +54,17 @@ ret const BYTE BasicEffect_PSBasic[] = { - 68, 88, 66, 67, 114, 189, - 168, 120, 224, 136, 133, 44, - 131, 14, 127, 119, 149, 15, - 203, 133, 1, 0, 0, 0, - 200, 3, 0, 0, 4, 0, + 68, 88, 66, 67, 144, 213, + 146, 10, 42, 151, 153, 148, + 98, 38, 10, 116, 201, 247, + 238, 241, 1, 0, 0, 0, + 212, 3, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 152, 2, 0, 0, 76, 3, - 0, 0, 148, 3, 0, 0, - 65, 111, 110, 57, 96, 2, - 0, 0, 96, 2, 0, 0, - 0, 2, 255, 255, 48, 2, + 164, 2, 0, 0, 88, 3, + 0, 0, 160, 3, 0, 0, + 65, 111, 110, 57, 108, 2, + 0, 0, 108, 2, 0, 0, + 0, 2, 255, 255, 60, 2, 0, 0, 48, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -72,7 +72,7 @@ const BYTE BasicEffect_PSBasic[] = 48, 0, 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 112, 0, 68, 66, + 254, 255, 115, 0, 68, 66, 85, 71, 40, 0, 0, 0, 148, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -80,7 +80,7 @@ const BYTE BasicEffect_PSBasic[] = 0, 0, 116, 0, 0, 0, 3, 0, 0, 0, 88, 1, 0, 0, 172, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -93,15 +93,15 @@ const BYTE BasicEffect_PSBasic[] = 67, 111, 109, 109, 111, 110, 46, 102, 120, 104, 0, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 200, 1, 0, 0, - 0, 0, 255, 255, 212, 1, + 255, 255, 212, 1, 0, 0, + 0, 0, 255, 255, 224, 1, 0, 0, 20, 0, 0, 0, - 224, 1, 0, 0, 20, 0, - 0, 0, 244, 1, 0, 0, - 20, 0, 0, 0, 0, 2, + 236, 1, 0, 0, 20, 0, + 0, 0, 0, 2, 0, 0, + 20, 0, 0, 0, 12, 2, 0, 0, 20, 0, 0, 0, - 20, 2, 0, 0, 20, 0, - 0, 0, 32, 2, 0, 0, + 32, 2, 0, 0, 20, 0, + 0, 0, 44, 2, 0, 0, 80, 83, 66, 97, 115, 105, 99, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0, @@ -147,7 +147,9 @@ const BYTE BasicEffect_PSBasic[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc index 04d4c419..ea10994a 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc @@ -22,7 +22,7 @@ ps_2_0 dcl t0 // pin<0,1,2,3> -#line 337 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 337 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oC0, t0 // ::PSBasicNoFog<0,1,2,3> // approximately 1 instruction slot used @@ -36,23 +36,23 @@ ret const BYTE BasicEffect_PSBasicNoFog[] = { - 68, 88, 66, 67, 39, 255, - 148, 232, 240, 134, 106, 55, - 30, 193, 83, 236, 196, 128, - 65, 237, 1, 0, 0, 0, - 108, 2, 0, 0, 4, 0, + 68, 88, 66, 67, 71, 62, + 194, 137, 38, 29, 1, 76, + 235, 155, 245, 79, 249, 175, + 85, 193, 1, 0, 0, 0, + 120, 2, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 200, 1, 0, 0, 8, 2, - 0, 0, 56, 2, 0, 0, - 65, 111, 110, 57, 144, 1, - 0, 0, 144, 1, 0, 0, - 0, 2, 255, 255, 108, 1, + 212, 1, 0, 0, 20, 2, + 0, 0, 68, 2, 0, 0, + 65, 111, 110, 57, 156, 1, + 0, 0, 156, 1, 0, 0, + 0, 2, 255, 255, 120, 1, 0, 0, 36, 0, 0, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 2, 255, 255, - 254, 255, 82, 0, 68, 66, + 254, 255, 85, 0, 68, 66, 85, 71, 40, 0, 0, 0, 28, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -60,7 +60,7 @@ const BYTE BasicEffect_PSBasicNoFog[] = 0, 0, 120, 0, 0, 0, 2, 0, 0, 0, 244, 0, 0, 0, 136, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -74,8 +74,8 @@ const BYTE BasicEffect_PSBasicNoFog[] = 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 40, 0, 0, 0, 0, 0, 255, 255, - 80, 1, 0, 0, 81, 1, - 0, 0, 92, 1, 0, 0, + 92, 1, 0, 0, 81, 1, + 0, 0, 104, 1, 0, 0, 80, 83, 66, 97, 115, 105, 99, 78, 111, 70, 111, 103, 0, 171, 171, 171, 1, 0, @@ -107,7 +107,9 @@ const BYTE BasicEffect_PSBasicNoFog[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc index aaae3cbd..39bec39c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc @@ -34,10 +34,10 @@ dcl t1.xyz // pin<4,5,6> dcl t2 // pin<7,8,9,10> -#line 411 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 411 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" nrm r0.xyz, t1 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r1.x, -c3, r0 // ::dotL<0> dp3 r1.y, -c4, r0 // ::dotL<1> dp3 r1.z, -c5, r0 // ::dotL<2> @@ -46,12 +46,12 @@ cmp r2.xyz, r1, c14.x, c14.y // ::zeroL<0,1,2> mul r1.xyz, r1, r2 // ::diffuse<0,1,2> -#line 410 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 410 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" add r3.xyz, -t0, c12 dp3 r0.w, r3, r3 rsq r0.w, r0.w -#line 33 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 33 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mad r4.xyz, r3, r0.w, -c3 nrm r5.xyz, r4 // ::halfVectors<0,1,2> @@ -93,17 +93,17 @@ mad r0.xyz, r2.w, c11, r0 mul r0.xyz, r0, c2 // ::result<3,4,5> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mul r0.xyz, r0, t2.w -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mul r2.xyz, r1.y, c7 mad r2.xyz, r1.x, c6, r2 mad r1.xyz, r1.z, c8, r2 mov r2.xyz, c0 // Parameters::DiffuseColor<0,1,2> mad r1.xyz, r1, r2, c1 // ::result<0,1,2> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r0.xyz, t2, r1, r0 // AddSpecular::color<0,1,2> #line 20 @@ -171,17 +171,17 @@ ret const BYTE BasicEffect_PSBasicPixelLighting[] = { - 68, 88, 66, 67, 227, 187, - 214, 151, 65, 25, 169, 106, - 56, 182, 107, 171, 138, 197, - 93, 49, 1, 0, 0, 0, - 252, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 1, 55, + 141, 141, 238, 139, 39, 81, + 2, 236, 197, 87, 198, 157, + 8, 158, 1, 0, 0, 0, + 8, 16, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 116, 9, 0, 0, 96, 15, - 0, 0, 200, 15, 0, 0, - 65, 111, 110, 57, 60, 9, - 0, 0, 60, 9, 0, 0, - 0, 2, 255, 255, 12, 9, + 128, 9, 0, 0, 108, 15, + 0, 0, 212, 15, 0, 0, + 65, 111, 110, 57, 72, 9, + 0, 0, 72, 9, 0, 0, + 0, 2, 255, 255, 24, 9, 0, 0, 48, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -189,7 +189,7 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 48, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 138, 1, 68, 66, + 254, 255, 141, 1, 68, 66, 85, 71, 40, 0, 0, 0, 252, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, @@ -197,7 +197,7 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 0, 0, 16, 1, 0, 0, 13, 0, 0, 0, 248, 4, 0, 0, 180, 2, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -209,7 +209,7 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 97, 100, 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -221,7 +221,7 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -236,67 +236,67 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 120, 104, 0, 171, 40, 0, 0, 0, 115, 0, 0, 0, 188, 0, 0, 0, 0, 0, - 255, 255, 48, 6, 0, 0, - 0, 0, 255, 255, 72, 6, + 255, 255, 60, 6, 0, 0, + 0, 0, 255, 255, 84, 6, 0, 0, 0, 0, 255, 255, - 84, 6, 0, 0, 0, 0, - 255, 255, 96, 6, 0, 0, - 155, 1, 0, 0, 108, 6, + 96, 6, 0, 0, 0, 0, + 255, 255, 108, 6, 0, 0, + 155, 1, 0, 0, 120, 6, 0, 0, 36, 0, 1, 0, - 120, 6, 0, 0, 36, 0, - 1, 0, 136, 6, 0, 0, - 36, 0, 1, 0, 152, 6, + 132, 6, 0, 0, 36, 0, + 1, 0, 148, 6, 0, 0, + 36, 0, 1, 0, 164, 6, 0, 0, 39, 0, 1, 0, - 168, 6, 0, 0, 41, 0, - 1, 0, 188, 6, 0, 0, - 154, 1, 0, 0, 204, 6, + 180, 6, 0, 0, 41, 0, + 1, 0, 200, 6, 0, 0, + 154, 1, 0, 0, 216, 6, 0, 0, 154, 1, 0, 0, - 220, 6, 0, 0, 154, 1, - 0, 0, 236, 6, 0, 0, - 33, 0, 1, 0, 248, 6, + 232, 6, 0, 0, 154, 1, + 0, 0, 248, 6, 0, 0, + 33, 0, 1, 0, 4, 7, 0, 0, 33, 0, 1, 0, - 12, 7, 0, 0, 37, 0, - 1, 0, 24, 7, 0, 0, - 33, 0, 1, 0, 40, 7, + 24, 7, 0, 0, 37, 0, + 1, 0, 36, 7, 0, 0, + 33, 0, 1, 0, 52, 7, 0, 0, 33, 0, 1, 0, - 60, 7, 0, 0, 33, 0, - 1, 0, 80, 7, 0, 0, - 37, 0, 1, 0, 92, 7, + 72, 7, 0, 0, 33, 0, + 1, 0, 92, 7, 0, 0, + 37, 0, 1, 0, 104, 7, 0, 0, 33, 0, 1, 0, - 108, 7, 0, 0, 37, 0, - 1, 0, 120, 7, 0, 0, - 42, 0, 1, 0, 136, 7, + 120, 7, 0, 0, 37, 0, + 1, 0, 132, 7, 0, 0, + 42, 0, 1, 0, 148, 7, 0, 0, 42, 0, 1, 0, - 152, 7, 0, 0, 42, 0, - 1, 0, 172, 7, 0, 0, - 42, 0, 1, 0, 184, 7, + 164, 7, 0, 0, 42, 0, + 1, 0, 184, 7, 0, 0, + 42, 0, 1, 0, 196, 7, 0, 0, 42, 0, 1, 0, - 196, 7, 0, 0, 42, 0, - 1, 0, 208, 7, 0, 0, - 42, 0, 1, 0, 224, 7, + 208, 7, 0, 0, 42, 0, + 1, 0, 220, 7, 0, 0, + 42, 0, 1, 0, 236, 7, 0, 0, 47, 0, 1, 0, - 236, 7, 0, 0, 42, 0, - 1, 0, 252, 7, 0, 0, - 42, 0, 1, 0, 8, 8, + 248, 7, 0, 0, 42, 0, + 1, 0, 8, 8, 0, 0, + 42, 0, 1, 0, 20, 8, 0, 0, 47, 0, 1, 0, - 20, 8, 0, 0, 47, 0, - 1, 0, 40, 8, 0, 0, - 47, 0, 1, 0, 60, 8, + 32, 8, 0, 0, 47, 0, + 1, 0, 52, 8, 0, 0, + 47, 0, 1, 0, 72, 8, 0, 0, 26, 0, 2, 0, - 76, 8, 0, 0, 46, 0, - 1, 0, 92, 8, 0, 0, - 46, 0, 1, 0, 108, 8, + 88, 8, 0, 0, 46, 0, + 1, 0, 104, 8, 0, 0, + 46, 0, 1, 0, 120, 8, 0, 0, 46, 0, 1, 0, - 128, 8, 0, 0, 46, 0, - 1, 0, 148, 8, 0, 0, - 46, 0, 1, 0, 160, 8, + 140, 8, 0, 0, 46, 0, + 1, 0, 160, 8, 0, 0, + 46, 0, 1, 0, 172, 8, 0, 0, 26, 0, 2, 0, - 180, 8, 0, 0, 20, 0, - 2, 0, 200, 8, 0, 0, - 20, 0, 2, 0, 220, 8, + 192, 8, 0, 0, 20, 0, + 2, 0, 212, 8, 0, 0, + 20, 0, 2, 0, 232, 8, 0, 0, 20, 0, 2, 0, - 240, 8, 0, 0, 20, 0, - 2, 0, 252, 8, 0, 0, + 252, 8, 0, 0, 20, 0, + 2, 0, 8, 9, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -452,7 +452,9 @@ const BYTE BasicEffect_PSBasicPixelLighting[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 14, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc index 45a342c8..6065ed1a 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc @@ -44,13 +44,13 @@ dcl t3 // pin<9,10,11,12> dcl_2d s0 -#line 427 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 427 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" texld r0, t0, s0 #line 430 nrm r1.xyz, t2 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, -c3, r1 // ::dotL<0> dp3 r2.y, -c4, r1 // ::dotL<1> dp3 r2.z, -c5, r1 // ::dotL<2> @@ -59,12 +59,12 @@ cmp r3.xyz, r2, c14.x, c14.y // ::zeroL<0,1,2> mul r2.xyz, r2, r3 // ::diffuse<0,1,2> -#line 429 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 429 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" add r4.xyz, -t1, c12 dp3 r1.w, r4, r4 rsq r1.w, r1.w -#line 33 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 33 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mad r5.xyz, r4, r1.w, -c3 nrm r6.xyz, r5 // ::halfVectors<0,1,2> @@ -106,20 +106,20 @@ mad r1.xyz, r3.w, c11, r1 mul r1.xyz, r1, c2 // ::result<3,4,5> -#line 427 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 427 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul r0, r0, t3 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mul r1.xyz, r0.w, r1 -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mul r3.xyz, r2.y, c7 mad r3.xyz, r2.x, c6, r3 mad r2.xyz, r2.z, c8, r3 mov r3.xyz, c0 // Parameters::DiffuseColor<0,1,2> mad r2.xyz, r2, r3, c1 // ::result<0,1,2> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, r0, r2, r1 // AddSpecular::color<0,1,2> #line 20 @@ -191,17 +191,17 @@ ret const BYTE BasicEffect_PSBasicPixelLightingTx[] = { - 68, 88, 66, 67, 161, 21, - 26, 188, 147, 113, 169, 193, - 213, 164, 203, 139, 151, 130, - 20, 162, 1, 0, 0, 0, - 20, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 225, 233, + 212, 21, 229, 103, 1, 60, + 236, 208, 251, 255, 120, 10, + 74, 19, 1, 0, 0, 0, + 32, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 12, 10, 0, 0, 96, 16, - 0, 0, 224, 16, 0, 0, - 65, 111, 110, 57, 212, 9, - 0, 0, 212, 9, 0, 0, - 0, 2, 255, 255, 160, 9, + 24, 10, 0, 0, 108, 16, + 0, 0, 236, 16, 0, 0, + 65, 111, 110, 57, 224, 9, + 0, 0, 224, 9, 0, 0, + 0, 2, 255, 255, 172, 9, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -210,14 +210,14 @@ const BYTE BasicEffect_PSBasicPixelLightingTx[] = 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 164, 1, 68, 66, 85, 71, + 167, 1, 68, 66, 85, 71, 40, 0, 0, 0, 100, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 49, 0, 0, 0, 16, 1, 0, 0, 14, 0, 0, 0, 76, 5, 0, 0, - 204, 2, 0, 0, 67, 58, + 204, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -230,7 +230,7 @@ const BYTE BasicEffect_PSBasicPixelLightingTx[] = 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, 120, - 0, 67, 58, 92, 65, 84, + 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, @@ -242,7 +242,7 @@ const BYTE BasicEffect_PSBasicPixelLightingTx[] = 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, 102, 120, - 104, 0, 67, 58, 92, 65, + 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -257,71 +257,71 @@ const BYTE BasicEffect_PSBasicPixelLightingTx[] = 0, 171, 40, 0, 0, 0, 115, 0, 0, 0, 188, 0, 0, 0, 0, 0, 255, 255, - 152, 6, 0, 0, 0, 0, - 255, 255, 176, 6, 0, 0, - 0, 0, 255, 255, 188, 6, + 164, 6, 0, 0, 0, 0, + 255, 255, 188, 6, 0, 0, + 0, 0, 255, 255, 200, 6, 0, 0, 0, 0, 255, 255, - 200, 6, 0, 0, 0, 0, - 255, 255, 212, 6, 0, 0, - 0, 0, 255, 255, 224, 6, + 212, 6, 0, 0, 0, 0, + 255, 255, 224, 6, 0, 0, + 0, 0, 255, 255, 236, 6, 0, 0, 171, 1, 0, 0, - 236, 6, 0, 0, 174, 1, - 0, 0, 252, 6, 0, 0, - 36, 0, 1, 0, 8, 7, + 248, 6, 0, 0, 174, 1, + 0, 0, 8, 7, 0, 0, + 36, 0, 1, 0, 20, 7, 0, 0, 36, 0, 1, 0, - 24, 7, 0, 0, 36, 0, - 1, 0, 40, 7, 0, 0, - 39, 0, 1, 0, 56, 7, + 36, 7, 0, 0, 36, 0, + 1, 0, 52, 7, 0, 0, + 39, 0, 1, 0, 68, 7, 0, 0, 41, 0, 1, 0, - 76, 7, 0, 0, 173, 1, - 0, 0, 92, 7, 0, 0, - 173, 1, 0, 0, 108, 7, + 88, 7, 0, 0, 173, 1, + 0, 0, 104, 7, 0, 0, + 173, 1, 0, 0, 120, 7, 0, 0, 173, 1, 0, 0, - 124, 7, 0, 0, 33, 0, - 1, 0, 136, 7, 0, 0, - 33, 0, 1, 0, 156, 7, + 136, 7, 0, 0, 33, 0, + 1, 0, 148, 7, 0, 0, + 33, 0, 1, 0, 168, 7, 0, 0, 37, 0, 1, 0, - 168, 7, 0, 0, 33, 0, - 1, 0, 184, 7, 0, 0, - 33, 0, 1, 0, 204, 7, + 180, 7, 0, 0, 33, 0, + 1, 0, 196, 7, 0, 0, + 33, 0, 1, 0, 216, 7, 0, 0, 33, 0, 1, 0, - 224, 7, 0, 0, 37, 0, - 1, 0, 236, 7, 0, 0, - 33, 0, 1, 0, 252, 7, + 236, 7, 0, 0, 37, 0, + 1, 0, 248, 7, 0, 0, + 33, 0, 1, 0, 8, 8, 0, 0, 37, 0, 1, 0, - 8, 8, 0, 0, 42, 0, - 1, 0, 24, 8, 0, 0, - 42, 0, 1, 0, 40, 8, + 20, 8, 0, 0, 42, 0, + 1, 0, 36, 8, 0, 0, + 42, 0, 1, 0, 52, 8, 0, 0, 42, 0, 1, 0, - 60, 8, 0, 0, 42, 0, - 1, 0, 72, 8, 0, 0, - 42, 0, 1, 0, 84, 8, + 72, 8, 0, 0, 42, 0, + 1, 0, 84, 8, 0, 0, + 42, 0, 1, 0, 96, 8, 0, 0, 42, 0, 1, 0, - 96, 8, 0, 0, 42, 0, - 1, 0, 112, 8, 0, 0, - 47, 0, 1, 0, 124, 8, + 108, 8, 0, 0, 42, 0, + 1, 0, 124, 8, 0, 0, + 47, 0, 1, 0, 136, 8, 0, 0, 42, 0, 1, 0, - 140, 8, 0, 0, 42, 0, - 1, 0, 152, 8, 0, 0, - 47, 0, 1, 0, 164, 8, + 152, 8, 0, 0, 42, 0, + 1, 0, 164, 8, 0, 0, + 47, 0, 1, 0, 176, 8, 0, 0, 47, 0, 1, 0, - 184, 8, 0, 0, 47, 0, - 1, 0, 204, 8, 0, 0, - 171, 1, 0, 0, 220, 8, + 196, 8, 0, 0, 47, 0, + 1, 0, 216, 8, 0, 0, + 171, 1, 0, 0, 232, 8, 0, 0, 26, 0, 2, 0, - 236, 8, 0, 0, 46, 0, - 1, 0, 252, 8, 0, 0, - 46, 0, 1, 0, 12, 9, + 248, 8, 0, 0, 46, 0, + 1, 0, 8, 9, 0, 0, + 46, 0, 1, 0, 24, 9, 0, 0, 46, 0, 1, 0, - 32, 9, 0, 0, 46, 0, - 1, 0, 52, 9, 0, 0, - 46, 0, 1, 0, 64, 9, + 44, 9, 0, 0, 46, 0, + 1, 0, 64, 9, 0, 0, + 46, 0, 1, 0, 76, 9, 0, 0, 26, 0, 2, 0, - 84, 9, 0, 0, 20, 0, - 2, 0, 104, 9, 0, 0, - 20, 0, 2, 0, 124, 9, + 96, 9, 0, 0, 20, 0, + 2, 0, 116, 9, 0, 0, + 20, 0, 2, 0, 136, 9, 0, 0, 20, 0, 2, 0, - 144, 9, 0, 0, 80, 97, + 156, 9, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, 67, 111, @@ -490,7 +490,9 @@ const BYTE BasicEffect_PSBasicPixelLightingTx[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 14, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc index 8a6433a6..af95054c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc @@ -41,11 +41,11 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 344 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 344 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" texld r0, t2, s0 mul r0, r0, t0 // ::color<0,1,2,3> -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, c0, r0.w, -r0 mad r0.xyz, t1.w, r1, r0 // ApplyFog::color<0,1,2> mov oC0, r0 // ::PSBasicTx<0,1,2,3> @@ -71,17 +71,17 @@ ret const BYTE BasicEffect_PSBasicTx[] = { - 68, 88, 66, 67, 188, 186, - 68, 183, 113, 27, 163, 65, - 177, 98, 193, 7, 58, 127, - 141, 151, 1, 0, 0, 0, - 24, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 12, 246, + 6, 35, 46, 21, 42, 46, + 181, 41, 112, 166, 143, 179, + 170, 18, 1, 0, 0, 0, + 36, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 96, 3, 0, 0, 124, 4, - 0, 0, 228, 4, 0, 0, - 65, 111, 110, 57, 40, 3, - 0, 0, 40, 3, 0, 0, - 0, 2, 255, 255, 244, 2, + 108, 3, 0, 0, 136, 4, + 0, 0, 240, 4, 0, 0, + 65, 111, 110, 57, 52, 3, + 0, 0, 52, 3, 0, 0, + 0, 2, 255, 255, 0, 3, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -90,14 +90,14 @@ const BYTE BasicEffect_PSBasicTx[] = 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 153, 0, 68, 66, 85, 71, + 156, 0, 68, 66, 85, 71, 40, 0, 0, 0, 56, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 9, 0, 0, 0, 196, 0, 0, 0, 4, 0, 0, 0, 232, 1, 0, 0, - 12, 1, 0, 0, 67, 58, + 12, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -110,7 +110,7 @@ const BYTE BasicEffect_PSBasicTx[] = 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, 120, - 0, 67, 58, 92, 65, 84, + 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, @@ -124,18 +124,18 @@ const BYTE BasicEffect_PSBasicTx[] = 110, 46, 102, 120, 104, 0, 171, 171, 40, 0, 0, 0, 115, 0, 0, 0, 0, 0, - 255, 255, 108, 2, 0, 0, - 0, 0, 255, 255, 120, 2, + 255, 255, 120, 2, 0, 0, + 0, 0, 255, 255, 132, 2, 0, 0, 0, 0, 255, 255, - 132, 2, 0, 0, 0, 0, - 255, 255, 144, 2, 0, 0, - 88, 1, 0, 0, 156, 2, + 144, 2, 0, 0, 0, 0, + 255, 255, 156, 2, 0, 0, + 88, 1, 0, 0, 168, 2, 0, 0, 88, 1, 0, 0, - 172, 2, 0, 0, 20, 0, - 1, 0, 188, 2, 0, 0, - 20, 0, 1, 0, 208, 2, + 184, 2, 0, 0, 20, 0, + 1, 0, 200, 2, 0, 0, + 20, 0, 1, 0, 220, 2, 0, 0, 20, 0, 1, 0, - 228, 2, 0, 0, 80, 83, + 240, 2, 0, 0, 80, 83, 66, 97, 115, 105, 99, 84, 120, 0, 171, 171, 1, 0, 3, 0, 1, 0, 4, 0, @@ -192,7 +192,9 @@ const BYTE BasicEffect_PSBasicTx[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc index 995d40a1..203ff9f4 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc @@ -32,7 +32,7 @@ dcl t1.xy // pin<4,5> dcl_2d s0 -#line 355 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 355 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" texld r0, t1, s0 mul r0, r0, t0 // ::PSBasicTxNoFog<0,1,2,3> mov oC0, r0 // ::PSBasicTxNoFog<0,1,2,3> @@ -53,31 +53,31 @@ ret const BYTE BasicEffect_PSBasicTxNoFog[] = { - 68, 88, 66, 67, 202, 62, - 43, 24, 24, 167, 50, 82, - 241, 156, 231, 82, 42, 172, - 68, 12, 1, 0, 0, 0, - 128, 3, 0, 0, 4, 0, + 68, 88, 66, 67, 154, 40, + 86, 105, 130, 38, 173, 144, + 185, 17, 127, 166, 55, 147, + 104, 63, 1, 0, 0, 0, + 140, 3, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 96, 2, 0, 0, 252, 2, - 0, 0, 76, 3, 0, 0, - 65, 111, 110, 57, 40, 2, - 0, 0, 40, 2, 0, 0, - 0, 2, 255, 255, 0, 2, + 108, 2, 0, 0, 8, 3, + 0, 0, 88, 3, 0, 0, + 65, 111, 110, 57, 52, 2, + 0, 0, 52, 2, 0, 0, + 0, 2, 255, 255, 12, 2, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 105, 0, 68, 66, 85, 71, + 108, 0, 68, 66, 85, 71, 40, 0, 0, 0, 120, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 120, 0, 0, 0, 2, 0, 0, 0, 80, 1, 0, 0, - 168, 0, 0, 0, 67, 58, + 168, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -91,14 +91,14 @@ const BYTE BasicEffect_PSBasicTxNoFog[] = 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 172, 1, + 0, 0, 255, 255, 184, 1, 0, 0, 0, 0, 255, 255, - 184, 1, 0, 0, 0, 0, - 255, 255, 196, 1, 0, 0, - 99, 1, 0, 0, 208, 1, + 196, 1, 0, 0, 0, 0, + 255, 255, 208, 1, 0, 0, + 99, 1, 0, 0, 220, 1, 0, 0, 99, 1, 0, 0, - 224, 1, 0, 0, 99, 1, - 0, 0, 240, 1, 0, 0, + 236, 1, 0, 0, 99, 1, + 0, 0, 252, 1, 0, 0, 80, 83, 66, 97, 115, 105, 99, 84, 120, 78, 111, 70, 111, 103, 0, 171, 1, 0, @@ -140,7 +140,9 @@ const BYTE BasicEffect_PSBasicTxNoFog[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc index 0ce1f0bb..a73646cc 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc @@ -31,7 +31,7 @@ dcl t0 // pin<0,1,2,3> dcl t1 // pin<4,5,6,7> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov r0, t0 // pin<0,1,2,3> mad r0.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> @@ -58,17 +58,17 @@ ret const BYTE BasicEffect_PSBasicVertexLighting[] = { - 68, 88, 66, 67, 18, 102, - 41, 118, 121, 177, 81, 62, - 18, 101, 73, 36, 154, 122, - 83, 100, 1, 0, 0, 0, - 68, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 85, 84, + 21, 236, 108, 84, 43, 246, + 195, 173, 160, 136, 202, 82, + 26, 132, 1, 0, 0, 0, + 80, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 240, 2, 0, 0, 200, 3, - 0, 0, 16, 4, 0, 0, - 65, 111, 110, 57, 184, 2, - 0, 0, 184, 2, 0, 0, - 0, 2, 255, 255, 136, 2, + 252, 2, 0, 0, 212, 3, + 0, 0, 28, 4, 0, 0, + 65, 111, 110, 57, 196, 2, + 0, 0, 196, 2, 0, 0, + 0, 2, 255, 255, 148, 2, 0, 0, 48, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -76,7 +76,7 @@ const BYTE BasicEffect_PSBasicVertexLighting[] = 48, 0, 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 129, 0, 68, 66, + 254, 255, 132, 0, 68, 66, 85, 71, 40, 0, 0, 0, 216, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -84,7 +84,7 @@ const BYTE BasicEffect_PSBasicVertexLighting[] = 0, 0, 116, 0, 0, 0, 4, 0, 0, 0, 136, 1, 0, 0, 180, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -97,16 +97,16 @@ const BYTE BasicEffect_PSBasicVertexLighting[] = 67, 111, 109, 109, 111, 110, 46, 102, 120, 104, 0, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 12, 2, 0, 0, - 0, 0, 255, 255, 24, 2, + 255, 255, 24, 2, 0, 0, + 0, 0, 255, 255, 36, 2, 0, 0, 26, 0, 0, 0, - 36, 2, 0, 0, 26, 0, - 0, 0, 48, 2, 0, 0, - 20, 0, 0, 0, 68, 2, + 48, 2, 0, 0, 26, 0, + 0, 0, 60, 2, 0, 0, + 20, 0, 0, 0, 80, 2, 0, 0, 20, 0, 0, 0, - 88, 2, 0, 0, 20, 0, - 0, 0, 108, 2, 0, 0, - 20, 0, 0, 0, 120, 2, + 100, 2, 0, 0, 20, 0, + 0, 0, 120, 2, 0, 0, + 20, 0, 0, 0, 132, 2, 0, 0, 80, 83, 66, 97, 115, 105, 99, 86, 101, 114, 116, 101, 120, 76, 105, 103, @@ -162,7 +162,9 @@ const BYTE BasicEffect_PSBasicVertexLighting[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc index c1594108..42f26531 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc @@ -24,7 +24,7 @@ dcl t0 // pin<0,1,2,3> dcl t1 // pin<4,5,6,7> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov r0, t0 // pin<0,1,2,3> mad r0.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> mov r0.w, t0.w @@ -43,23 +43,23 @@ ret const BYTE BasicEffect_PSBasicVertexLightingNoFog[] = { - 68, 88, 66, 67, 222, 218, - 17, 223, 30, 109, 53, 74, - 83, 79, 76, 240, 237, 58, - 25, 229, 1, 0, 0, 0, - 116, 3, 0, 0, 4, 0, + 68, 88, 66, 67, 233, 121, + 8, 241, 32, 247, 137, 149, + 161, 109, 168, 156, 18, 7, + 245, 50, 1, 0, 0, 0, + 128, 3, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 136, 2, 0, 0, 248, 2, - 0, 0, 64, 3, 0, 0, - 65, 111, 110, 57, 80, 2, - 0, 0, 80, 2, 0, 0, - 0, 2, 255, 255, 44, 2, + 148, 2, 0, 0, 4, 3, + 0, 0, 76, 3, 0, 0, + 65, 111, 110, 57, 92, 2, + 0, 0, 92, 2, 0, 0, + 0, 2, 255, 255, 56, 2, 0, 0, 36, 0, 0, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 2, 255, 255, - 254, 255, 116, 0, 68, 66, + 254, 255, 119, 0, 68, 66, 85, 71, 40, 0, 0, 0, 164, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -67,7 +67,7 @@ const BYTE BasicEffect_PSBasicVertexLightingNoFog[] = 0, 0, 116, 0, 0, 0, 3, 0, 0, 0, 104, 1, 0, 0, 164, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -80,14 +80,14 @@ const BYTE BasicEffect_PSBasicVertexLightingNoFog[] = 67, 111, 109, 109, 111, 110, 46, 102, 120, 104, 0, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 216, 1, 0, 0, - 0, 0, 255, 255, 228, 1, + 255, 255, 228, 1, 0, 0, + 0, 0, 255, 255, 240, 1, 0, 0, 26, 0, 0, 0, - 240, 1, 0, 0, 26, 0, - 0, 0, 252, 1, 0, 0, - 26, 0, 0, 0, 16, 2, + 252, 1, 0, 0, 26, 0, + 0, 0, 8, 2, 0, 0, + 26, 0, 0, 0, 28, 2, 0, 0, 26, 0, 0, 0, - 28, 2, 0, 0, 80, 83, + 40, 2, 0, 0, 80, 83, 66, 97, 115, 105, 99, 86, 101, 114, 116, 101, 120, 76, 105, 103, 104, 116, 105, 110, @@ -136,7 +136,9 @@ const BYTE BasicEffect_PSBasicVertexLightingNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc index 8ac3fc12..c7164cf6 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc @@ -41,11 +41,11 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 385 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 385 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" texld r0, t2, s0 mul r0, r0, t0 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> #line 20 @@ -75,17 +75,17 @@ ret const BYTE BasicEffect_PSBasicVertexLightingTx[] = { - 68, 88, 66, 67, 12, 45, - 32, 233, 77, 105, 178, 222, - 233, 127, 45, 216, 102, 162, - 107, 125, 1, 0, 0, 0, - 144, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 74, 168, + 233, 44, 228, 142, 191, 94, + 132, 217, 50, 67, 252, 133, + 87, 7, 1, 0, 0, 0, + 156, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 180, 3, 0, 0, 244, 4, - 0, 0, 92, 5, 0, 0, - 65, 111, 110, 57, 124, 3, - 0, 0, 124, 3, 0, 0, - 0, 2, 255, 255, 72, 3, + 192, 3, 0, 0, 0, 5, + 0, 0, 104, 5, 0, 0, + 65, 111, 110, 57, 136, 3, + 0, 0, 136, 3, 0, 0, + 0, 2, 255, 255, 84, 3, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -94,14 +94,14 @@ const BYTE BasicEffect_PSBasicVertexLightingTx[] = 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 169, 0, 68, 66, 85, 71, + 172, 0, 68, 66, 85, 71, 40, 0, 0, 0, 120, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 10, 0, 0, 0, 196, 0, 0, 0, 5, 0, 0, 0, 20, 2, 0, 0, - 20, 1, 0, 0, 67, 58, + 20, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -114,7 +114,7 @@ const BYTE BasicEffect_PSBasicVertexLightingTx[] = 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, 120, - 0, 67, 58, 92, 65, 84, + 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, @@ -128,19 +128,19 @@ const BYTE BasicEffect_PSBasicVertexLightingTx[] = 110, 46, 102, 120, 104, 0, 171, 171, 40, 0, 0, 0, 115, 0, 0, 0, 0, 0, - 255, 255, 172, 2, 0, 0, - 0, 0, 255, 255, 184, 2, + 255, 255, 184, 2, 0, 0, + 0, 0, 255, 255, 196, 2, 0, 0, 0, 0, 255, 255, - 196, 2, 0, 0, 0, 0, - 255, 255, 208, 2, 0, 0, - 129, 1, 0, 0, 220, 2, + 208, 2, 0, 0, 0, 0, + 255, 255, 220, 2, 0, 0, + 129, 1, 0, 0, 232, 2, 0, 0, 129, 1, 0, 0, - 236, 2, 0, 0, 26, 0, - 1, 0, 252, 2, 0, 0, - 20, 0, 1, 0, 16, 3, + 248, 2, 0, 0, 26, 0, + 1, 0, 8, 3, 0, 0, + 20, 0, 1, 0, 28, 3, 0, 0, 20, 0, 1, 0, - 36, 3, 0, 0, 20, 0, - 1, 0, 56, 3, 0, 0, + 48, 3, 0, 0, 20, 0, + 1, 0, 68, 3, 0, 0, 80, 83, 66, 97, 115, 105, 99, 86, 101, 114, 116, 101, 120, 76, 105, 103, 104, 116, @@ -206,7 +206,9 @@ const BYTE BasicEffect_PSBasicVertexLightingTx[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc index 04752bd2..52884330 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc @@ -34,11 +34,11 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 397 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 397 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" texld r0, t2, s0 mul r0, r0, t0 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r0.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> mov oC0, r0 // ::PSBasicVertexLightingTxNoFog<0,1,2,3> @@ -61,31 +61,31 @@ ret const BYTE BasicEffect_PSBasicVertexLightingTxNoFog[] = { - 68, 88, 66, 67, 102, 167, - 231, 71, 98, 80, 177, 139, - 206, 229, 55, 104, 245, 36, - 234, 197, 1, 0, 0, 0, - 204, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 85, 43, + 164, 222, 187, 49, 164, 113, + 33, 93, 63, 223, 12, 135, + 134, 162, 1, 0, 0, 0, + 216, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 80, 3, 0, 0, 48, 4, - 0, 0, 152, 4, 0, 0, - 65, 111, 110, 57, 24, 3, - 0, 0, 24, 3, 0, 0, - 0, 2, 255, 255, 240, 2, + 92, 3, 0, 0, 60, 4, + 0, 0, 164, 4, 0, 0, + 65, 111, 110, 57, 36, 3, + 0, 0, 36, 3, 0, 0, + 0, 2, 255, 255, 252, 2, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 157, 0, 68, 66, 85, 71, + 160, 0, 68, 66, 85, 71, 40, 0, 0, 0, 72, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 8, 0, 0, 0, 196, 0, 0, 0, 4, 0, 0, 0, 248, 1, 0, 0, - 4, 1, 0, 0, 67, 58, + 4, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -98,7 +98,7 @@ const BYTE BasicEffect_PSBasicVertexLightingTxNoFog[] = 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, 120, - 0, 67, 58, 92, 65, 84, + 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, @@ -112,16 +112,16 @@ const BYTE BasicEffect_PSBasicVertexLightingTxNoFog[] = 110, 46, 102, 120, 104, 0, 171, 171, 40, 0, 0, 0, 115, 0, 0, 0, 0, 0, - 255, 255, 124, 2, 0, 0, - 0, 0, 255, 255, 136, 2, + 255, 255, 136, 2, 0, 0, + 0, 0, 255, 255, 148, 2, 0, 0, 0, 0, 255, 255, - 148, 2, 0, 0, 0, 0, - 255, 255, 160, 2, 0, 0, - 141, 1, 0, 0, 172, 2, + 160, 2, 0, 0, 0, 0, + 255, 255, 172, 2, 0, 0, + 141, 1, 0, 0, 184, 2, 0, 0, 141, 1, 0, 0, - 188, 2, 0, 0, 26, 0, - 1, 0, 204, 2, 0, 0, - 26, 0, 1, 0, 224, 2, + 200, 2, 0, 0, 26, 0, + 1, 0, 216, 2, 0, 0, + 26, 0, 1, 0, 236, 2, 0, 0, 80, 83, 66, 97, 115, 105, 99, 86, 101, 114, 116, 101, 120, 76, 105, 103, @@ -182,7 +182,9 @@ const BYTE BasicEffect_PSBasicVertexLightingTxNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasic.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasic.inc index 3167d5da..048bb750 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasic.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasic.inc @@ -41,7 +41,7 @@ def c7, 0, 1, 0, 0 dcl_texcoord v0 // vin<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSBasic<10> #line 14 @@ -54,11 +54,11 @@ dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasic<8,9> mov oPos.w, r0.z // ::VSBasic<11> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSBasic<0,1,2,3> mov oT1.xyz, c7.x // ::VSBasic<4,5,6> @@ -82,17 +82,17 @@ ret const BYTE BasicEffect_VSBasic[] = { - 68, 88, 66, 67, 167, 3, - 36, 114, 168, 80, 114, 14, - 30, 56, 143, 162, 14, 97, - 122, 15, 1, 0, 0, 0, - 36, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 100, 48, + 155, 211, 252, 56, 204, 202, + 68, 23, 233, 41, 111, 177, + 218, 85, 1, 0, 0, 0, + 48, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 84, 4, 0, 0, 132, 5, - 0, 0, 184, 5, 0, 0, - 65, 111, 110, 57, 28, 4, - 0, 0, 28, 4, 0, 0, - 0, 2, 254, 255, 208, 3, + 96, 4, 0, 0, 144, 5, + 0, 0, 196, 5, 0, 0, + 65, 111, 110, 57, 40, 4, + 0, 0, 40, 4, 0, 0, + 0, 2, 254, 255, 220, 3, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -105,14 +105,14 @@ const BYTE BasicEffect_VSBasic[] = 4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 190, 0, 68, 66, 85, 71, + 193, 0, 68, 66, 85, 71, 40, 0, 0, 0, 204, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 13, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 144, 2, 0, 0, - 44, 1, 0, 0, 67, 58, + 44, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -124,7 +124,7 @@ const BYTE BasicEffect_VSBasic[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -139,23 +139,23 @@ const BYTE BasicEffect_VSBasic[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 0, 3, 0, 0, - 0, 0, 255, 255, 24, 3, + 255, 255, 12, 3, 0, 0, + 0, 0, 255, 255, 36, 3, 0, 0, 43, 0, 0, 0, - 36, 3, 0, 0, 14, 0, - 0, 0, 52, 3, 0, 0, - 14, 0, 0, 0, 68, 3, + 48, 3, 0, 0, 14, 0, + 0, 0, 64, 3, 0, 0, + 14, 0, 0, 0, 80, 3, 0, 0, 14, 0, 0, 0, - 84, 3, 0, 0, 43, 0, - 0, 0, 100, 3, 0, 0, - 43, 0, 0, 0, 116, 3, + 96, 3, 0, 0, 43, 0, + 0, 0, 112, 3, 0, 0, + 43, 0, 0, 0, 128, 3, 0, 0, 43, 0, 0, 0, - 132, 3, 0, 0, 44, 0, - 1, 0, 148, 3, 0, 0, - 44, 0, 1, 0, 168, 3, + 144, 3, 0, 0, 44, 0, + 1, 0, 160, 3, 0, 0, + 44, 0, 1, 0, 180, 3, 0, 0, 44, 0, 0, 0, - 180, 3, 0, 0, 45, 0, - 0, 0, 192, 3, 0, 0, + 192, 3, 0, 0, 45, 0, + 0, 0, 204, 3, 0, 0, 86, 83, 66, 97, 115, 105, 99, 0, 68, 105, 102, 102, 117, 115, 101, 0, 1, 0, @@ -231,7 +231,9 @@ const BYTE BasicEffect_VSBasic[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc index 61f31576..582a22ad 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc @@ -38,17 +38,17 @@ vs_2_0 dcl_texcoord v0 // vin<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSBasicNoFog<6> dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 56 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 56 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicNoFog<4,5> mov oPos.w, r0.z // ::VSBasicNoFog<7> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSBasicNoFog<0,1,2,3> // approximately 7 instruction slots used @@ -68,17 +68,17 @@ ret const BYTE BasicEffect_VSBasicNoFog[] = { - 68, 88, 66, 67, 73, 95, - 170, 11, 2, 152, 180, 140, - 155, 123, 152, 92, 110, 224, - 155, 128, 1, 0, 0, 0, - 36, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 18, 161, + 118, 62, 174, 20, 46, 175, + 213, 87, 11, 225, 105, 52, + 240, 195, 1, 0, 0, 0, + 48, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 184, 3, 0, 0, 156, 4, - 0, 0, 208, 4, 0, 0, - 65, 111, 110, 57, 128, 3, - 0, 0, 128, 3, 0, 0, - 0, 2, 254, 255, 64, 3, + 196, 3, 0, 0, 168, 4, + 0, 0, 220, 4, 0, 0, + 65, 111, 110, 57, 140, 3, + 0, 0, 140, 3, 0, 0, + 0, 2, 254, 255, 76, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -89,14 +89,14 @@ const BYTE BasicEffect_VSBasicNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 175, 0, 68, 66, 85, 71, + 178, 0, 68, 66, 85, 71, 40, 0, 0, 0, 144, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 8, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 84, 2, 0, 0, - 4, 1, 0, 0, 67, 58, + 4, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -108,7 +108,7 @@ const BYTE BasicEffect_VSBasicNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -123,16 +123,16 @@ const BYTE BasicEffect_VSBasicNoFog[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 196, 2, 0, 0, - 43, 0, 0, 0, 208, 2, + 255, 255, 208, 2, 0, 0, + 43, 0, 0, 0, 220, 2, 0, 0, 43, 0, 0, 0, - 224, 2, 0, 0, 43, 0, - 0, 0, 240, 2, 0, 0, - 43, 0, 0, 0, 0, 3, + 236, 2, 0, 0, 43, 0, + 0, 0, 252, 2, 0, 0, + 43, 0, 0, 0, 12, 3, 0, 0, 56, 0, 1, 0, - 16, 3, 0, 0, 56, 0, - 1, 0, 36, 3, 0, 0, - 44, 0, 0, 0, 48, 3, + 28, 3, 0, 0, 56, 0, + 1, 0, 48, 3, 0, 0, + 44, 0, 0, 0, 60, 3, 0, 0, 86, 83, 66, 97, 115, 105, 99, 78, 111, 70, 111, 103, 0, 68, 105, 102, @@ -205,7 +205,9 @@ const BYTE BasicEffect_VSBasicNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 9, 0, 0, 3, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc index 2296ab46..391cf479 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc @@ -46,7 +46,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5,6> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, v1, c12 dp3 r0.y, v1, c13 dp3 r0.z, v1, c14 @@ -90,21 +90,21 @@ #line 63 dp4 oPos.z, v0, c17 // ::VSBasicOneLight<10> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c8 max r0.x, r0.x, c19.x min oT1.w, r0.x, c19.y // ::VSBasicOneLight<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::vout<0> dp4 r0.y, v0, c16 // ::vout<1> dp4 r0.z, v0, c18 // ::vout<3> -#line 209 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 209 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicOneLight<8,9> mov oPos.w, r0.z // ::VSBasicOneLight<11> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c1.w // ::VSBasicOneLight<3> // approximately 41 instruction slots used @@ -158,17 +158,17 @@ ret const BYTE BasicEffect_VSBasicOneLight[] = { - 68, 88, 66, 67, 126, 201, - 141, 129, 108, 101, 79, 192, - 42, 19, 6, 176, 114, 68, - 39, 18, 1, 0, 0, 0, - 80, 14, 0, 0, 4, 0, + 68, 88, 66, 67, 30, 10, + 24, 11, 90, 191, 233, 204, + 206, 104, 111, 148, 225, 132, + 204, 3, 1, 0, 0, 0, + 92, 14, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 244, 8, 0, 0, 144, 13, - 0, 0, 228, 13, 0, 0, - 65, 111, 110, 57, 188, 8, - 0, 0, 188, 8, 0, 0, - 0, 2, 254, 255, 76, 8, + 0, 9, 0, 0, 156, 13, + 0, 0, 240, 13, 0, 0, + 65, 111, 110, 57, 200, 8, + 0, 0, 200, 8, 0, 0, + 0, 2, 254, 255, 88, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -187,14 +187,14 @@ const BYTE BasicEffect_VSBasicOneLight[] = 7, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 132, 1, 68, 66, 85, 71, + 135, 1, 68, 66, 85, 71, 40, 0, 0, 0, 228, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 36, 0, 0, 0, 16, 1, 0, 0, 13, 0, 0, 0, 224, 4, 0, 0, - 100, 2, 0, 0, 67, 58, + 100, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -206,7 +206,7 @@ const BYTE BasicEffect_VSBasicOneLight[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -218,7 +218,7 @@ const BYTE BasicEffect_VSBasicOneLight[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -234,53 +234,53 @@ const BYTE BasicEffect_VSBasicOneLight[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 24, 6, 0, 0, 0, 0, - 255, 255, 48, 6, 0, 0, - 0, 0, 255, 255, 60, 6, + 36, 6, 0, 0, 0, 0, + 255, 255, 60, 6, 0, 0, + 0, 0, 255, 255, 72, 6, 0, 0, 59, 0, 0, 0, - 72, 6, 0, 0, 59, 0, - 0, 0, 88, 6, 0, 0, - 59, 0, 0, 0, 104, 6, + 84, 6, 0, 0, 59, 0, + 0, 0, 100, 6, 0, 0, + 59, 0, 0, 0, 116, 6, 0, 0, 59, 0, 0, 0, - 120, 6, 0, 0, 36, 0, - 0, 0, 132, 6, 0, 0, - 39, 0, 0, 0, 148, 6, + 132, 6, 0, 0, 36, 0, + 0, 0, 144, 6, 0, 0, + 39, 0, 0, 0, 160, 6, 0, 0, 41, 0, 0, 0, - 164, 6, 0, 0, 46, 0, - 0, 0, 180, 6, 0, 0, - 46, 0, 0, 0, 196, 6, + 176, 6, 0, 0, 46, 0, + 0, 0, 192, 6, 0, 0, + 46, 0, 0, 0, 208, 6, 0, 0, 46, 0, 0, 0, - 208, 6, 0, 0, 57, 0, - 0, 0, 228, 6, 0, 0, - 57, 0, 0, 0, 244, 6, + 220, 6, 0, 0, 57, 0, + 0, 0, 240, 6, 0, 0, + 57, 0, 0, 0, 0, 7, 0, 0, 57, 0, 0, 0, - 4, 7, 0, 0, 58, 0, - 0, 0, 20, 7, 0, 0, - 58, 0, 0, 0, 36, 7, + 16, 7, 0, 0, 58, 0, + 0, 0, 32, 7, 0, 0, + 58, 0, 0, 0, 48, 7, 0, 0, 33, 0, 0, 0, - 48, 7, 0, 0, 33, 0, - 0, 0, 64, 7, 0, 0, - 37, 0, 0, 0, 76, 7, + 60, 7, 0, 0, 33, 0, + 0, 0, 76, 7, 0, 0, + 37, 0, 0, 0, 88, 7, 0, 0, 42, 0, 0, 0, - 92, 7, 0, 0, 42, 0, - 0, 0, 108, 7, 0, 0, - 42, 0, 0, 0, 124, 7, + 104, 7, 0, 0, 42, 0, + 0, 0, 120, 7, 0, 0, + 42, 0, 0, 0, 136, 7, 0, 0, 47, 0, 0, 0, - 140, 7, 0, 0, 47, 0, - 0, 0, 156, 7, 0, 0, - 63, 0, 0, 0, 172, 7, + 152, 7, 0, 0, 47, 0, + 0, 0, 168, 7, 0, 0, + 63, 0, 0, 0, 184, 7, 0, 0, 14, 0, 1, 0, - 188, 7, 0, 0, 14, 0, - 1, 0, 204, 7, 0, 0, - 14, 0, 1, 0, 220, 7, + 200, 7, 0, 0, 14, 0, + 1, 0, 216, 7, 0, 0, + 14, 0, 1, 0, 232, 7, 0, 0, 63, 0, 0, 0, - 236, 7, 0, 0, 63, 0, - 0, 0, 252, 7, 0, 0, - 63, 0, 0, 0, 12, 8, + 248, 7, 0, 0, 63, 0, + 0, 0, 8, 8, 0, 0, + 63, 0, 0, 0, 24, 8, 0, 0, 209, 0, 2, 0, - 28, 8, 0, 0, 209, 0, - 2, 0, 48, 8, 0, 0, - 46, 0, 0, 0, 60, 8, + 40, 8, 0, 0, 209, 0, + 2, 0, 60, 8, 0, 0, + 46, 0, 0, 0, 72, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -445,7 +445,9 @@ const BYTE BasicEffect_VSBasicOneLight[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 19, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc index 64741abf..2a0bf6e4 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc @@ -49,7 +49,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, v1, c12 dp3 r0.y, v1, c13 dp3 r0.z, v1, c14 @@ -93,24 +93,24 @@ #line 63 dp4 oPos.z, v0, c17 // ::VSBasicOneLightTx<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c8 max r0.x, r0.x, c19.x min oT1.w, r0.x, c19.y // ::VSBasicOneLightTx<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::vout<0> dp4 r0.y, v0, c16 // ::vout<1> dp4 r0.z, v0, c18 // ::vout<3> -#line 235 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 235 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicOneLightTx<10,11> mov oPos.w, r0.z // ::VSBasicOneLightTx<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c1.w // ::VSBasicOneLightTx<3> -#line 242 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 242 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oT2.xy, v2 // ::VSBasicOneLightTx<8,9> // approximately 42 instruction slots used @@ -167,17 +167,17 @@ ret const BYTE BasicEffect_VSBasicOneLightTx[] = { - 68, 88, 66, 67, 134, 215, - 145, 17, 37, 56, 176, 20, - 208, 22, 88, 246, 152, 83, - 101, 85, 1, 0, 0, 0, - 44, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 64, 206, + 14, 129, 76, 126, 142, 143, + 192, 221, 233, 93, 60, 182, + 203, 201, 1, 0, 0, 0, + 56, 15, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 100, 9, 0, 0, 44, 14, - 0, 0, 160, 14, 0, 0, - 65, 111, 110, 57, 44, 9, - 0, 0, 44, 9, 0, 0, - 0, 2, 254, 255, 188, 8, + 112, 9, 0, 0, 56, 14, + 0, 0, 172, 14, 0, 0, + 65, 111, 110, 57, 56, 9, + 0, 0, 56, 9, 0, 0, + 0, 2, 254, 255, 200, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -196,14 +196,14 @@ const BYTE BasicEffect_VSBasicOneLightTx[] = 7, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 154, 1, 68, 66, 85, 71, + 157, 1, 68, 66, 85, 71, 40, 0, 0, 0, 60, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 38, 0, 0, 0, 16, 1, 0, 0, 13, 0, 0, 0, 56, 5, 0, 0, - 116, 2, 0, 0, 67, 58, + 116, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -215,7 +215,7 @@ const BYTE BasicEffect_VSBasicOneLightTx[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -227,7 +227,7 @@ const BYTE BasicEffect_VSBasicOneLightTx[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -243,56 +243,56 @@ const BYTE BasicEffect_VSBasicOneLightTx[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 112, 6, 0, 0, 0, 0, - 255, 255, 136, 6, 0, 0, - 0, 0, 255, 255, 148, 6, + 124, 6, 0, 0, 0, 0, + 255, 255, 148, 6, 0, 0, + 0, 0, 255, 255, 160, 6, 0, 0, 0, 0, 255, 255, - 160, 6, 0, 0, 59, 0, - 0, 0, 172, 6, 0, 0, - 59, 0, 0, 0, 188, 6, + 172, 6, 0, 0, 59, 0, + 0, 0, 184, 6, 0, 0, + 59, 0, 0, 0, 200, 6, 0, 0, 59, 0, 0, 0, - 204, 6, 0, 0, 59, 0, - 0, 0, 220, 6, 0, 0, - 36, 0, 0, 0, 232, 6, + 216, 6, 0, 0, 59, 0, + 0, 0, 232, 6, 0, 0, + 36, 0, 0, 0, 244, 6, 0, 0, 39, 0, 0, 0, - 248, 6, 0, 0, 41, 0, - 0, 0, 8, 7, 0, 0, - 46, 0, 0, 0, 24, 7, + 4, 7, 0, 0, 41, 0, + 0, 0, 20, 7, 0, 0, + 46, 0, 0, 0, 36, 7, 0, 0, 46, 0, 0, 0, - 40, 7, 0, 0, 46, 0, - 0, 0, 52, 7, 0, 0, - 57, 0, 0, 0, 72, 7, + 52, 7, 0, 0, 46, 0, + 0, 0, 64, 7, 0, 0, + 57, 0, 0, 0, 84, 7, 0, 0, 57, 0, 0, 0, - 88, 7, 0, 0, 57, 0, - 0, 0, 104, 7, 0, 0, - 58, 0, 0, 0, 120, 7, + 100, 7, 0, 0, 57, 0, + 0, 0, 116, 7, 0, 0, + 58, 0, 0, 0, 132, 7, 0, 0, 58, 0, 0, 0, - 136, 7, 0, 0, 33, 0, - 0, 0, 148, 7, 0, 0, - 33, 0, 0, 0, 164, 7, + 148, 7, 0, 0, 33, 0, + 0, 0, 160, 7, 0, 0, + 33, 0, 0, 0, 176, 7, 0, 0, 37, 0, 0, 0, - 176, 7, 0, 0, 42, 0, - 0, 0, 192, 7, 0, 0, - 42, 0, 0, 0, 208, 7, + 188, 7, 0, 0, 42, 0, + 0, 0, 204, 7, 0, 0, + 42, 0, 0, 0, 220, 7, 0, 0, 42, 0, 0, 0, - 224, 7, 0, 0, 47, 0, - 0, 0, 240, 7, 0, 0, - 47, 0, 0, 0, 0, 8, + 236, 7, 0, 0, 47, 0, + 0, 0, 252, 7, 0, 0, + 47, 0, 0, 0, 12, 8, 0, 0, 63, 0, 0, 0, - 16, 8, 0, 0, 14, 0, - 1, 0, 32, 8, 0, 0, - 14, 0, 1, 0, 48, 8, + 28, 8, 0, 0, 14, 0, + 1, 0, 44, 8, 0, 0, + 14, 0, 1, 0, 60, 8, 0, 0, 14, 0, 1, 0, - 64, 8, 0, 0, 63, 0, - 0, 0, 80, 8, 0, 0, - 63, 0, 0, 0, 96, 8, + 76, 8, 0, 0, 63, 0, + 0, 0, 92, 8, 0, 0, + 63, 0, 0, 0, 108, 8, 0, 0, 63, 0, 0, 0, - 112, 8, 0, 0, 235, 0, - 2, 0, 128, 8, 0, 0, - 235, 0, 2, 0, 148, 8, + 124, 8, 0, 0, 235, 0, + 2, 0, 140, 8, 0, 0, + 235, 0, 2, 0, 160, 8, 0, 0, 46, 0, 0, 0, - 160, 8, 0, 0, 242, 0, - 2, 0, 172, 8, 0, 0, + 172, 8, 0, 0, 242, 0, + 2, 0, 184, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -469,7 +469,9 @@ const BYTE BasicEffect_VSBasicOneLightTx[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 19, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc index 97cacbfa..3cb9328d 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc @@ -51,7 +51,7 @@ dcl_texcoord2 v2 // vin<7,8> dcl_texcoord3 v3 // vin<9,10,11,12> -#line 57 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 57 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::pos_ws<0> dp4 r0.y, v0, c10 // ::pos_ws<1> dp4 r0.z, v0, c11 // ::pos_ws<2> @@ -87,26 +87,26 @@ mov r1.xyz, c1 // Parameters::DiffuseColor<0,1,2> mad r0.xyz, r0, r1, c2 // ::result<0,1,2> -#line 257 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 257 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.xyz, r0, v3 // ::VSBasicOneLightTxVc<0,1,2> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c17 // ::VSBasicOneLightTxVc<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c8 max r0.x, r0.x, c19.x min oT1.w, r0.x, c19.y // ::VSBasicOneLightTxVc<7> -#line 257 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 257 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.w, v3.w, c1.w // ::VSBasicOneLightTxVc<3> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::vout<0> dp4 r0.y, v0, c16 // ::vout<1> dp4 r0.z, v0, c18 // ::vout<3> -#line 249 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 249 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicOneLightTxVc<10,11> mov oPos.w, r0.z // ::VSBasicOneLightTxVc<13> @@ -169,17 +169,17 @@ ret const BYTE BasicEffect_VSBasicOneLightTxVc[] = { - 68, 88, 66, 67, 151, 80, - 197, 35, 22, 212, 204, 240, - 24, 227, 137, 220, 42, 70, - 119, 97, 1, 0, 0, 0, - 248, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 145, 67, + 128, 118, 193, 195, 146, 208, + 43, 93, 115, 43, 72, 134, + 83, 3, 1, 0, 0, 0, + 4, 16, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 224, 9, 0, 0, 216, 14, - 0, 0, 108, 15, 0, 0, - 65, 111, 110, 57, 168, 9, - 0, 0, 168, 9, 0, 0, - 0, 2, 254, 255, 56, 9, + 236, 9, 0, 0, 228, 14, + 0, 0, 120, 15, 0, 0, + 65, 111, 110, 57, 180, 9, + 0, 0, 180, 9, 0, 0, + 0, 2, 254, 255, 68, 9, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -198,14 +198,14 @@ const BYTE BasicEffect_VSBasicOneLightTxVc[] = 7, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 181, 1, 68, 66, 85, 71, + 184, 1, 68, 66, 85, 71, 40, 0, 0, 0, 168, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 39, 0, 0, 0, 16, 1, 0, 0, 14, 0, 0, 0, 144, 5, 0, 0, - 124, 2, 0, 0, 67, 58, + 124, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -217,7 +217,7 @@ const BYTE BasicEffect_VSBasicOneLightTxVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -230,7 +230,7 @@ const BYTE BasicEffect_VSBasicOneLightTxVc[] = 100, 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, - 120, 0, 67, 58, 92, 65, + 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -245,57 +245,57 @@ const BYTE BasicEffect_VSBasicOneLightTxVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 188, 0, 0, 0, 0, 0, 255, 255, - 220, 6, 0, 0, 0, 0, - 255, 255, 244, 6, 0, 0, - 0, 0, 255, 255, 0, 7, + 232, 6, 0, 0, 0, 0, + 255, 255, 0, 7, 0, 0, + 0, 0, 255, 255, 12, 7, 0, 0, 0, 0, 255, 255, - 12, 7, 0, 0, 0, 0, - 255, 255, 24, 7, 0, 0, - 57, 0, 0, 0, 36, 7, + 24, 7, 0, 0, 0, 0, + 255, 255, 36, 7, 0, 0, + 57, 0, 0, 0, 48, 7, 0, 0, 57, 0, 0, 0, - 52, 7, 0, 0, 57, 0, - 0, 0, 68, 7, 0, 0, - 58, 0, 0, 0, 84, 7, + 64, 7, 0, 0, 57, 0, + 0, 0, 80, 7, 0, 0, + 58, 0, 0, 0, 96, 7, 0, 0, 58, 0, 0, 0, - 100, 7, 0, 0, 33, 0, - 0, 0, 112, 7, 0, 0, - 33, 0, 0, 0, 128, 7, + 112, 7, 0, 0, 33, 0, + 0, 0, 124, 7, 0, 0, + 33, 0, 0, 0, 140, 7, 0, 0, 59, 0, 0, 0, - 140, 7, 0, 0, 59, 0, - 0, 0, 156, 7, 0, 0, - 59, 0, 0, 0, 172, 7, + 152, 7, 0, 0, 59, 0, + 0, 0, 168, 7, 0, 0, + 59, 0, 0, 0, 184, 7, 0, 0, 59, 0, 0, 0, - 188, 7, 0, 0, 37, 0, - 0, 0, 200, 7, 0, 0, - 36, 0, 0, 0, 216, 7, + 200, 7, 0, 0, 37, 0, + 0, 0, 212, 7, 0, 0, + 36, 0, 0, 0, 228, 7, 0, 0, 42, 0, 0, 0, - 232, 7, 0, 0, 39, 0, - 0, 0, 248, 7, 0, 0, - 41, 0, 0, 0, 8, 8, + 244, 7, 0, 0, 39, 0, + 0, 0, 4, 8, 0, 0, + 41, 0, 0, 0, 20, 8, 0, 0, 42, 0, 0, 0, - 24, 8, 0, 0, 47, 0, - 0, 0, 40, 8, 0, 0, - 47, 0, 0, 0, 56, 8, + 36, 8, 0, 0, 47, 0, + 0, 0, 52, 8, 0, 0, + 47, 0, 0, 0, 68, 8, 0, 0, 46, 0, 0, 0, - 72, 8, 0, 0, 46, 0, - 0, 0, 88, 8, 0, 0, - 46, 0, 0, 0, 100, 8, + 84, 8, 0, 0, 46, 0, + 0, 0, 100, 8, 0, 0, + 46, 0, 0, 0, 112, 8, 0, 0, 1, 1, 1, 0, - 120, 8, 0, 0, 63, 0, - 0, 0, 136, 8, 0, 0, - 14, 0, 2, 0, 152, 8, + 132, 8, 0, 0, 63, 0, + 0, 0, 148, 8, 0, 0, + 14, 0, 2, 0, 164, 8, 0, 0, 14, 0, 2, 0, - 168, 8, 0, 0, 14, 0, - 2, 0, 184, 8, 0, 0, - 1, 1, 1, 0, 200, 8, + 180, 8, 0, 0, 14, 0, + 2, 0, 196, 8, 0, 0, + 1, 1, 1, 0, 212, 8, 0, 0, 63, 0, 0, 0, - 216, 8, 0, 0, 63, 0, - 0, 0, 232, 8, 0, 0, - 63, 0, 0, 0, 248, 8, + 228, 8, 0, 0, 63, 0, + 0, 0, 244, 8, 0, 0, + 63, 0, 0, 0, 4, 9, 0, 0, 249, 0, 1, 0, - 8, 9, 0, 0, 249, 0, - 1, 0, 28, 9, 0, 0, - 0, 1, 1, 0, 40, 9, + 20, 9, 0, 0, 249, 0, + 1, 0, 40, 9, 0, 0, + 0, 1, 1, 0, 52, 9, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -489,7 +489,9 @@ const BYTE BasicEffect_VSBasicOneLightTxVc[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 19, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc index 43a6cc9b..a24b96c9 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc @@ -48,7 +48,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8,9,10> -#line 57 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 57 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::pos_ws<0> dp4 r0.y, v0, c10 // ::pos_ws<1> dp4 r0.z, v0, c11 // ::pos_ws<2> @@ -84,26 +84,26 @@ mov r1.xyz, c1 // Parameters::DiffuseColor<0,1,2> mad r0.xyz, r0, r1, c2 // ::result<0,1,2> -#line 228 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 228 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.xyz, r0, v2 // ::VSBasicOneLightVc<0,1,2> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c17 // ::VSBasicOneLightVc<10> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c8 max r0.x, r0.x, c19.x min oT1.w, r0.x, c19.y // ::VSBasicOneLightVc<7> -#line 228 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 228 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.w, v2.w, c1.w // ::VSBasicOneLightVc<3> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::vout<0> dp4 r0.y, v0, c16 // ::vout<1> dp4 r0.z, v0, c18 // ::vout<3> -#line 221 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 221 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicOneLightVc<8,9> mov oPos.w, r0.z // ::VSBasicOneLightVc<11> @@ -160,17 +160,17 @@ ret const BYTE BasicEffect_VSBasicOneLightVc[] = { - 68, 88, 66, 67, 7, 204, - 182, 223, 154, 182, 35, 146, - 95, 111, 61, 221, 117, 48, - 242, 64, 1, 0, 0, 0, - 32, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 239, 38, + 243, 179, 54, 55, 7, 157, + 234, 80, 242, 217, 245, 120, + 226, 232, 1, 0, 0, 0, + 44, 15, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 116, 9, 0, 0, 64, 14, - 0, 0, 180, 14, 0, 0, - 65, 111, 110, 57, 60, 9, - 0, 0, 60, 9, 0, 0, - 0, 2, 254, 255, 204, 8, + 128, 9, 0, 0, 76, 14, + 0, 0, 192, 14, 0, 0, + 65, 111, 110, 57, 72, 9, + 0, 0, 72, 9, 0, 0, + 0, 2, 254, 255, 216, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -189,14 +189,14 @@ const BYTE BasicEffect_VSBasicOneLightVc[] = 7, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 160, 1, 68, 66, 85, 71, + 163, 1, 68, 66, 85, 71, 40, 0, 0, 0, 84, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 37, 0, 0, 0, 16, 1, 0, 0, 14, 0, 0, 0, 60, 5, 0, 0, - 108, 2, 0, 0, 67, 58, + 108, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -208,7 +208,7 @@ const BYTE BasicEffect_VSBasicOneLightVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -221,7 +221,7 @@ const BYTE BasicEffect_VSBasicOneLightVc[] = 100, 101, 114, 115, 92, 66, 97, 115, 105, 99, 69, 102, 102, 101, 99, 116, 46, 102, - 120, 0, 67, 58, 92, 65, + 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -236,55 +236,55 @@ const BYTE BasicEffect_VSBasicOneLightVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 188, 0, 0, 0, 0, 0, 255, 255, - 136, 6, 0, 0, 0, 0, - 255, 255, 160, 6, 0, 0, - 0, 0, 255, 255, 172, 6, + 148, 6, 0, 0, 0, 0, + 255, 255, 172, 6, 0, 0, + 0, 0, 255, 255, 184, 6, 0, 0, 0, 0, 255, 255, - 184, 6, 0, 0, 57, 0, - 0, 0, 196, 6, 0, 0, - 57, 0, 0, 0, 212, 6, + 196, 6, 0, 0, 57, 0, + 0, 0, 208, 6, 0, 0, + 57, 0, 0, 0, 224, 6, 0, 0, 57, 0, 0, 0, - 228, 6, 0, 0, 58, 0, - 0, 0, 244, 6, 0, 0, - 58, 0, 0, 0, 4, 7, + 240, 6, 0, 0, 58, 0, + 0, 0, 0, 7, 0, 0, + 58, 0, 0, 0, 16, 7, 0, 0, 33, 0, 0, 0, - 16, 7, 0, 0, 33, 0, - 0, 0, 32, 7, 0, 0, - 59, 0, 0, 0, 44, 7, + 28, 7, 0, 0, 33, 0, + 0, 0, 44, 7, 0, 0, + 59, 0, 0, 0, 56, 7, 0, 0, 59, 0, 0, 0, - 60, 7, 0, 0, 59, 0, - 0, 0, 76, 7, 0, 0, - 59, 0, 0, 0, 92, 7, + 72, 7, 0, 0, 59, 0, + 0, 0, 88, 7, 0, 0, + 59, 0, 0, 0, 104, 7, 0, 0, 37, 0, 0, 0, - 104, 7, 0, 0, 36, 0, - 0, 0, 120, 7, 0, 0, - 42, 0, 0, 0, 136, 7, + 116, 7, 0, 0, 36, 0, + 0, 0, 132, 7, 0, 0, + 42, 0, 0, 0, 148, 7, 0, 0, 39, 0, 0, 0, - 152, 7, 0, 0, 41, 0, - 0, 0, 168, 7, 0, 0, - 42, 0, 0, 0, 184, 7, + 164, 7, 0, 0, 41, 0, + 0, 0, 180, 7, 0, 0, + 42, 0, 0, 0, 196, 7, 0, 0, 47, 0, 0, 0, - 200, 7, 0, 0, 47, 0, - 0, 0, 216, 7, 0, 0, - 46, 0, 0, 0, 232, 7, + 212, 7, 0, 0, 47, 0, + 0, 0, 228, 7, 0, 0, + 46, 0, 0, 0, 244, 7, 0, 0, 46, 0, 0, 0, - 248, 7, 0, 0, 46, 0, - 0, 0, 4, 8, 0, 0, - 228, 0, 1, 0, 24, 8, + 4, 8, 0, 0, 46, 0, + 0, 0, 16, 8, 0, 0, + 228, 0, 1, 0, 36, 8, 0, 0, 63, 0, 0, 0, - 40, 8, 0, 0, 14, 0, - 2, 0, 56, 8, 0, 0, - 14, 0, 2, 0, 72, 8, + 52, 8, 0, 0, 14, 0, + 2, 0, 68, 8, 0, 0, + 14, 0, 2, 0, 84, 8, 0, 0, 14, 0, 2, 0, - 88, 8, 0, 0, 228, 0, - 1, 0, 104, 8, 0, 0, - 63, 0, 0, 0, 120, 8, + 100, 8, 0, 0, 228, 0, + 1, 0, 116, 8, 0, 0, + 63, 0, 0, 0, 132, 8, 0, 0, 63, 0, 0, 0, - 136, 8, 0, 0, 63, 0, - 0, 0, 152, 8, 0, 0, - 221, 0, 1, 0, 168, 8, + 148, 8, 0, 0, 63, 0, + 0, 0, 164, 8, 0, 0, + 221, 0, 1, 0, 180, 8, 0, 0, 221, 0, 1, 0, - 188, 8, 0, 0, 80, 97, + 200, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, 67, 111, @@ -466,7 +466,9 @@ const BYTE BasicEffect_VSBasicOneLightVc[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 19, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc index 247876ef..88353bb0 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc @@ -44,7 +44,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5,6> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c11 // ::VSBasicPixelLighting<13> dp4 oT0.x, v0, c3 // ::VSBasicPixelLighting<0> dp4 oT0.y, v0, c4 // ::VSBasicPixelLighting<1> @@ -56,17 +56,17 @@ rsq r0.w, r0.w mul oT1.xyz, r0.w, r0 // ::VSBasicPixelLighting<4,5,6> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 max r0.x, r0.x, c13.x min oT0.w, r0.x, c13.y // ::VSBasicPixelLighting<3> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::vout<0> dp4 r0.y, v0, c10 // ::vout<1> dp4 r0.z, v0, c12 // ::vout<3> -#line 264 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 264 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicPixelLighting<11,12> mov oPos.w, r0.z // ::VSBasicPixelLighting<14> @@ -106,17 +106,17 @@ ret const BYTE BasicEffect_VSBasicPixelLighting[] = { - 68, 88, 66, 67, 39, 177, - 182, 232, 221, 182, 217, 45, - 115, 127, 129, 125, 2, 196, - 138, 212, 1, 0, 0, 0, - 60, 9, 0, 0, 4, 0, + 68, 88, 66, 67, 203, 88, + 189, 107, 107, 234, 179, 42, + 210, 80, 132, 223, 14, 46, + 11, 35, 1, 0, 0, 0, + 72, 9, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 0, 6, 0, 0, 92, 8, - 0, 0, 176, 8, 0, 0, - 65, 111, 110, 57, 200, 5, - 0, 0, 200, 5, 0, 0, - 0, 2, 254, 255, 124, 5, + 12, 6, 0, 0, 104, 8, + 0, 0, 188, 8, 0, 0, + 65, 111, 110, 57, 212, 5, + 0, 0, 212, 5, 0, 0, + 0, 2, 254, 255, 136, 5, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -129,14 +129,14 @@ const BYTE BasicEffect_VSBasicPixelLighting[] = 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 1, 1, 68, 66, 85, 71, + 4, 1, 68, 66, 85, 71, 40, 0, 0, 0, 216, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 23, 0, 0, 0, 16, 1, 0, 0, 3, 0, 0, 0, 156, 3, 0, 0, - 200, 1, 0, 0, 67, 58, + 200, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -148,7 +148,7 @@ const BYTE BasicEffect_VSBasicPixelLighting[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -160,7 +160,7 @@ const BYTE BasicEffect_VSBasicPixelLighting[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -176,36 +176,36 @@ const BYTE BasicEffect_VSBasicPixelLighting[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 12, 4, 0, 0, 0, 0, - 255, 255, 36, 4, 0, 0, - 0, 0, 255, 255, 48, 4, + 24, 4, 0, 0, 0, 0, + 255, 255, 48, 4, 0, 0, + 0, 0, 255, 255, 60, 4, 0, 0, 85, 0, 0, 0, - 60, 4, 0, 0, 86, 0, - 0, 0, 76, 4, 0, 0, - 86, 0, 0, 0, 92, 4, + 72, 4, 0, 0, 86, 0, + 0, 0, 88, 4, 0, 0, + 86, 0, 0, 0, 104, 4, 0, 0, 86, 0, 0, 0, - 108, 4, 0, 0, 87, 0, - 0, 0, 124, 4, 0, 0, - 87, 0, 0, 0, 140, 4, + 120, 4, 0, 0, 87, 0, + 0, 0, 136, 4, 0, 0, + 87, 0, 0, 0, 152, 4, 0, 0, 87, 0, 0, 0, - 156, 4, 0, 0, 87, 0, - 0, 0, 172, 4, 0, 0, - 87, 0, 0, 0, 188, 4, + 168, 4, 0, 0, 87, 0, + 0, 0, 184, 4, 0, 0, + 87, 0, 0, 0, 200, 4, 0, 0, 87, 0, 0, 0, - 200, 4, 0, 0, 14, 0, - 1, 0, 216, 4, 0, 0, - 14, 0, 1, 0, 232, 4, + 212, 4, 0, 0, 14, 0, + 1, 0, 228, 4, 0, 0, + 14, 0, 1, 0, 244, 4, 0, 0, 14, 0, 1, 0, - 248, 4, 0, 0, 85, 0, - 0, 0, 8, 5, 0, 0, - 85, 0, 0, 0, 24, 5, + 4, 5, 0, 0, 85, 0, + 0, 0, 20, 5, 0, 0, + 85, 0, 0, 0, 36, 5, 0, 0, 85, 0, 0, 0, - 40, 5, 0, 0, 8, 1, - 2, 0, 56, 5, 0, 0, - 8, 1, 2, 0, 76, 5, + 52, 5, 0, 0, 8, 1, + 2, 0, 68, 5, 0, 0, + 8, 1, 2, 0, 88, 5, 0, 0, 15, 1, 2, 0, - 88, 5, 0, 0, 15, 1, - 2, 0, 100, 5, 0, 0, + 100, 5, 0, 0, 15, 1, + 2, 0, 112, 5, 0, 0, 86, 83, 66, 97, 115, 105, 99, 80, 105, 120, 101, 108, 76, 105, 103, 104, 116, 105, @@ -300,7 +300,9 @@ const BYTE BasicEffect_VSBasicPixelLighting[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc index deb37ea8..6c3e7194 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc @@ -47,7 +47,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c11 // ::VSBasicPixelLightingTx<15> dp4 oT1.x, v0, c3 // ::VSBasicPixelLightingTx<2> dp4 oT1.y, v0, c4 // ::VSBasicPixelLightingTx<3> @@ -59,17 +59,17 @@ rsq r0.w, r0.w mul oT2.xyz, r0.w, r0 // ::VSBasicPixelLightingTx<6,7,8> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 max r0.x, r0.x, c13.x min oT1.w, r0.x, c13.y // ::VSBasicPixelLightingTx<5> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::vout<0> dp4 r0.y, v0, c10 // ::vout<1> dp4 r0.z, v0, c12 // ::vout<3> -#line 293 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 293 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicPixelLightingTx<13,14> mov oPos.w, r0.z // ::VSBasicPixelLightingTx<16> @@ -113,17 +113,17 @@ ret const BYTE BasicEffect_VSBasicPixelLightingTx[] = { - 68, 88, 66, 67, 9, 43, - 114, 249, 73, 170, 16, 32, - 157, 118, 165, 108, 81, 48, - 40, 188, 1, 0, 0, 0, - 12, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 17, 174, + 140, 206, 160, 28, 99, 124, + 19, 161, 39, 207, 57, 40, + 172, 107, 1, 0, 0, 0, + 24, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 108, 6, 0, 0, 244, 8, - 0, 0, 104, 9, 0, 0, - 65, 111, 110, 57, 52, 6, - 0, 0, 52, 6, 0, 0, - 0, 2, 254, 255, 232, 5, + 120, 6, 0, 0, 0, 9, + 0, 0, 116, 9, 0, 0, + 65, 111, 110, 57, 64, 6, + 0, 0, 64, 6, 0, 0, + 0, 2, 254, 255, 244, 5, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -136,14 +136,14 @@ const BYTE BasicEffect_VSBasicPixelLightingTx[] = 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 22, 1, 68, 66, 85, 71, + 25, 1, 68, 66, 85, 71, 40, 0, 0, 0, 44, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 25, 0, 0, 0, 16, 1, 0, 0, 3, 0, 0, 0, 240, 3, 0, 0, - 216, 1, 0, 0, 67, 58, + 216, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -155,7 +155,7 @@ const BYTE BasicEffect_VSBasicPixelLightingTx[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -167,7 +167,7 @@ const BYTE BasicEffect_VSBasicPixelLightingTx[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -183,39 +183,39 @@ const BYTE BasicEffect_VSBasicPixelLightingTx[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 96, 4, 0, 0, 0, 0, - 255, 255, 120, 4, 0, 0, - 0, 0, 255, 255, 132, 4, + 108, 4, 0, 0, 0, 0, + 255, 255, 132, 4, 0, 0, + 0, 0, 255, 255, 144, 4, 0, 0, 0, 0, 255, 255, - 144, 4, 0, 0, 85, 0, - 0, 0, 156, 4, 0, 0, - 86, 0, 0, 0, 172, 4, + 156, 4, 0, 0, 85, 0, + 0, 0, 168, 4, 0, 0, + 86, 0, 0, 0, 184, 4, 0, 0, 86, 0, 0, 0, - 188, 4, 0, 0, 86, 0, - 0, 0, 204, 4, 0, 0, - 87, 0, 0, 0, 220, 4, + 200, 4, 0, 0, 86, 0, + 0, 0, 216, 4, 0, 0, + 87, 0, 0, 0, 232, 4, 0, 0, 87, 0, 0, 0, - 236, 4, 0, 0, 87, 0, - 0, 0, 252, 4, 0, 0, - 87, 0, 0, 0, 12, 5, + 248, 4, 0, 0, 87, 0, + 0, 0, 8, 5, 0, 0, + 87, 0, 0, 0, 24, 5, 0, 0, 87, 0, 0, 0, - 28, 5, 0, 0, 87, 0, - 0, 0, 40, 5, 0, 0, - 14, 0, 1, 0, 56, 5, + 40, 5, 0, 0, 87, 0, + 0, 0, 52, 5, 0, 0, + 14, 0, 1, 0, 68, 5, 0, 0, 14, 0, 1, 0, - 72, 5, 0, 0, 14, 0, - 1, 0, 88, 5, 0, 0, - 85, 0, 0, 0, 104, 5, + 84, 5, 0, 0, 14, 0, + 1, 0, 100, 5, 0, 0, + 85, 0, 0, 0, 116, 5, 0, 0, 85, 0, 0, 0, - 120, 5, 0, 0, 85, 0, - 0, 0, 136, 5, 0, 0, - 37, 1, 2, 0, 152, 5, + 132, 5, 0, 0, 85, 0, + 0, 0, 148, 5, 0, 0, + 37, 1, 2, 0, 164, 5, 0, 0, 37, 1, 2, 0, - 172, 5, 0, 0, 45, 1, - 2, 0, 184, 5, 0, 0, - 44, 1, 2, 0, 196, 5, + 184, 5, 0, 0, 45, 1, + 2, 0, 196, 5, 0, 0, + 44, 1, 2, 0, 208, 5, 0, 0, 44, 1, 2, 0, - 208, 5, 0, 0, 86, 83, + 220, 5, 0, 0, 86, 83, 66, 97, 115, 105, 99, 80, 105, 120, 101, 108, 76, 105, 103, 104, 116, 105, 110, 103, @@ -321,7 +321,9 @@ const BYTE BasicEffect_VSBasicPixelLightingTx[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc index 8209f47c..c39876ba 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc @@ -49,7 +49,7 @@ dcl_texcoord2 v2 // vin<7,8> dcl_texcoord3 v3 // vin<9,10,11,12> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c11 // ::VSBasicPixelLightingTxVc<15> dp4 oT1.x, v0, c3 // ::VSBasicPixelLightingTxVc<2> dp4 oT1.y, v0, c4 // ::VSBasicPixelLightingTxVc<3> @@ -61,20 +61,20 @@ rsq r0.w, r0.w mul oT2.xyz, r0.w, r0 // ::VSBasicPixelLightingTxVc<6,7,8> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 max r0.x, r0.x, c13.x min oT1.w, r0.x, c13.y // ::VSBasicPixelLightingTxVc<5> -#line 316 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 316 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT3.w, v3.w, c1.w // ::VSBasicPixelLightingTxVc<12> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::vout<0> dp4 r0.y, v0, c10 // ::vout<1> dp4 r0.z, v0, c12 // ::vout<3> -#line 308 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 308 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicPixelLightingTxVc<13,14> mov oPos.w, r0.z // ::VSBasicPixelLightingTxVc<16> @@ -118,17 +118,17 @@ ret const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = { - 68, 88, 66, 67, 222, 13, - 104, 235, 159, 170, 215, 223, - 249, 129, 108, 227, 207, 189, - 48, 89, 1, 0, 0, 0, - 112, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 134, 70, + 8, 48, 165, 212, 235, 215, + 112, 251, 246, 221, 214, 110, + 207, 192, 1, 0, 0, 0, + 124, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 168, 6, 0, 0, 56, 9, - 0, 0, 204, 9, 0, 0, - 65, 111, 110, 57, 112, 6, - 0, 0, 112, 6, 0, 0, - 0, 2, 254, 255, 36, 6, + 180, 6, 0, 0, 68, 9, + 0, 0, 216, 9, 0, 0, + 65, 111, 110, 57, 124, 6, + 0, 0, 124, 6, 0, 0, + 0, 2, 254, 255, 48, 6, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -141,14 +141,14 @@ const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 35, 1, 68, 66, 85, 71, + 38, 1, 68, 66, 85, 71, 40, 0, 0, 0, 96, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 26, 0, 0, 0, 16, 1, 0, 0, 3, 0, 0, 0, 36, 4, 0, 0, - 224, 1, 0, 0, 67, 58, + 224, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -160,7 +160,7 @@ const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -172,7 +172,7 @@ const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -188,40 +188,40 @@ const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 148, 4, 0, 0, 0, 0, - 255, 255, 172, 4, 0, 0, - 0, 0, 255, 255, 184, 4, + 160, 4, 0, 0, 0, 0, + 255, 255, 184, 4, 0, 0, + 0, 0, 255, 255, 196, 4, 0, 0, 0, 0, 255, 255, - 196, 4, 0, 0, 0, 0, - 255, 255, 208, 4, 0, 0, - 85, 0, 0, 0, 220, 4, + 208, 4, 0, 0, 0, 0, + 255, 255, 220, 4, 0, 0, + 85, 0, 0, 0, 232, 4, 0, 0, 86, 0, 0, 0, - 236, 4, 0, 0, 86, 0, - 0, 0, 252, 4, 0, 0, - 86, 0, 0, 0, 12, 5, + 248, 4, 0, 0, 86, 0, + 0, 0, 8, 5, 0, 0, + 86, 0, 0, 0, 24, 5, 0, 0, 87, 0, 0, 0, - 28, 5, 0, 0, 87, 0, - 0, 0, 44, 5, 0, 0, - 87, 0, 0, 0, 60, 5, + 40, 5, 0, 0, 87, 0, + 0, 0, 56, 5, 0, 0, + 87, 0, 0, 0, 72, 5, 0, 0, 87, 0, 0, 0, - 76, 5, 0, 0, 87, 0, - 0, 0, 92, 5, 0, 0, - 87, 0, 0, 0, 104, 5, + 88, 5, 0, 0, 87, 0, + 0, 0, 104, 5, 0, 0, + 87, 0, 0, 0, 116, 5, 0, 0, 14, 0, 1, 0, - 120, 5, 0, 0, 14, 0, - 1, 0, 136, 5, 0, 0, - 14, 0, 1, 0, 152, 5, + 132, 5, 0, 0, 14, 0, + 1, 0, 148, 5, 0, 0, + 14, 0, 1, 0, 164, 5, 0, 0, 60, 1, 2, 0, - 168, 5, 0, 0, 85, 0, - 0, 0, 184, 5, 0, 0, - 85, 0, 0, 0, 200, 5, + 180, 5, 0, 0, 85, 0, + 0, 0, 196, 5, 0, 0, + 85, 0, 0, 0, 212, 5, 0, 0, 85, 0, 0, 0, - 216, 5, 0, 0, 52, 1, - 2, 0, 232, 5, 0, 0, - 52, 1, 2, 0, 252, 5, + 228, 5, 0, 0, 52, 1, + 2, 0, 244, 5, 0, 0, + 52, 1, 2, 0, 8, 6, 0, 0, 61, 1, 2, 0, - 8, 6, 0, 0, 59, 1, - 2, 0, 20, 6, 0, 0, + 20, 6, 0, 0, 59, 1, + 2, 0, 32, 6, 0, 0, 86, 83, 66, 97, 115, 105, 99, 80, 105, 120, 101, 108, 76, 105, 103, 104, 116, 105, @@ -335,7 +335,9 @@ const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc index b0af53ec..8cb24e55 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc @@ -46,7 +46,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8,9,10> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 oPos.z, v0, c11 // ::VSBasicPixelLightingVc<13> dp4 oT0.x, v0, c3 // ::VSBasicPixelLightingVc<0> dp4 oT0.y, v0, c4 // ::VSBasicPixelLightingVc<1> @@ -58,20 +58,20 @@ rsq r0.w, r0.w mul oT1.xyz, r0.w, r0 // ::VSBasicPixelLightingVc<4,5,6> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 max r0.x, r0.x, c13.x min oT0.w, r0.x, c13.y // ::VSBasicPixelLightingVc<3> -#line 286 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 286 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT2.w, v2.w, c1.w // ::VSBasicPixelLightingVc<10> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c9 // ::vout<0> dp4 r0.y, v0, c10 // ::vout<1> dp4 r0.z, v0, c12 // ::vout<3> -#line 278 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 278 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicPixelLightingVc<11,12> mov oPos.w, r0.z // ::VSBasicPixelLightingVc<14> @@ -111,17 +111,17 @@ ret const BYTE BasicEffect_VSBasicPixelLightingVc[] = { - 68, 88, 66, 67, 21, 241, - 126, 7, 199, 62, 72, 9, - 249, 225, 57, 230, 105, 223, - 248, 207, 1, 0, 0, 0, - 160, 9, 0, 0, 4, 0, + 68, 88, 66, 67, 110, 63, + 70, 140, 228, 89, 128, 23, + 231, 246, 8, 127, 254, 119, + 199, 191, 1, 0, 0, 0, + 172, 9, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 60, 6, 0, 0, 160, 8, - 0, 0, 20, 9, 0, 0, - 65, 111, 110, 57, 4, 6, - 0, 0, 4, 6, 0, 0, - 0, 2, 254, 255, 184, 5, + 72, 6, 0, 0, 172, 8, + 0, 0, 32, 9, 0, 0, + 65, 111, 110, 57, 16, 6, + 0, 0, 16, 6, 0, 0, + 0, 2, 254, 255, 196, 5, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -134,14 +134,14 @@ const BYTE BasicEffect_VSBasicPixelLightingVc[] = 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 14, 1, 68, 66, 85, 71, + 17, 1, 68, 66, 85, 71, 40, 0, 0, 0, 12, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 24, 0, 0, 0, 16, 1, 0, 0, 3, 0, 0, 0, 208, 3, 0, 0, - 208, 1, 0, 0, 67, 58, + 208, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -153,7 +153,7 @@ const BYTE BasicEffect_VSBasicPixelLightingVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -165,7 +165,7 @@ const BYTE BasicEffect_VSBasicPixelLightingVc[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -181,37 +181,37 @@ const BYTE BasicEffect_VSBasicPixelLightingVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 64, 4, 0, 0, 0, 0, - 255, 255, 88, 4, 0, 0, - 0, 0, 255, 255, 100, 4, + 76, 4, 0, 0, 0, 0, + 255, 255, 100, 4, 0, 0, + 0, 0, 255, 255, 112, 4, 0, 0, 0, 0, 255, 255, - 112, 4, 0, 0, 85, 0, - 0, 0, 124, 4, 0, 0, - 86, 0, 0, 0, 140, 4, + 124, 4, 0, 0, 85, 0, + 0, 0, 136, 4, 0, 0, + 86, 0, 0, 0, 152, 4, 0, 0, 86, 0, 0, 0, - 156, 4, 0, 0, 86, 0, - 0, 0, 172, 4, 0, 0, - 87, 0, 0, 0, 188, 4, + 168, 4, 0, 0, 86, 0, + 0, 0, 184, 4, 0, 0, + 87, 0, 0, 0, 200, 4, 0, 0, 87, 0, 0, 0, - 204, 4, 0, 0, 87, 0, - 0, 0, 220, 4, 0, 0, - 87, 0, 0, 0, 236, 4, + 216, 4, 0, 0, 87, 0, + 0, 0, 232, 4, 0, 0, + 87, 0, 0, 0, 248, 4, 0, 0, 87, 0, 0, 0, - 252, 4, 0, 0, 87, 0, - 0, 0, 8, 5, 0, 0, - 14, 0, 1, 0, 24, 5, + 8, 5, 0, 0, 87, 0, + 0, 0, 20, 5, 0, 0, + 14, 0, 1, 0, 36, 5, 0, 0, 14, 0, 1, 0, - 40, 5, 0, 0, 14, 0, - 1, 0, 56, 5, 0, 0, - 30, 1, 2, 0, 72, 5, + 52, 5, 0, 0, 14, 0, + 1, 0, 68, 5, 0, 0, + 30, 1, 2, 0, 84, 5, 0, 0, 85, 0, 0, 0, - 88, 5, 0, 0, 85, 0, - 0, 0, 104, 5, 0, 0, - 85, 0, 0, 0, 120, 5, + 100, 5, 0, 0, 85, 0, + 0, 0, 116, 5, 0, 0, + 85, 0, 0, 0, 132, 5, 0, 0, 22, 1, 2, 0, - 136, 5, 0, 0, 22, 1, - 2, 0, 156, 5, 0, 0, - 29, 1, 2, 0, 168, 5, + 148, 5, 0, 0, 22, 1, + 2, 0, 168, 5, 0, 0, + 29, 1, 2, 0, 180, 5, 0, 0, 86, 83, 66, 97, 115, 105, 99, 80, 105, 120, 101, 108, 76, 105, 103, 104, @@ -314,7 +314,9 @@ const BYTE BasicEffect_VSBasicPixelLightingVc[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc index 4b9833d7..55fb7315 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc @@ -44,7 +44,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSBasicTx<12> #line 14 @@ -57,15 +57,15 @@ dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 96 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 96 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicTx<10,11> mov oPos.w, r0.z // ::VSBasicTx<13> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSBasicTx<0,1,2,3> mov oT1.xyz, c7.x // ::VSBasicTx<4,5,6> -#line 103 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 103 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oT2.xy, v1 // ::VSBasicTx<8,9> // approximately 12 instruction slots used @@ -91,17 +91,17 @@ ret const BYTE BasicEffect_VSBasicTx[] = { - 68, 88, 66, 67, 228, 129, - 100, 178, 242, 10, 146, 13, - 176, 148, 149, 179, 151, 217, - 176, 132, 1, 0, 0, 0, - 4, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 183, 10, + 102, 233, 28, 106, 76, 203, + 90, 87, 21, 213, 19, 22, + 213, 3, 1, 0, 0, 0, + 16, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 196, 4, 0, 0, 32, 6, - 0, 0, 120, 6, 0, 0, - 65, 111, 110, 57, 140, 4, - 0, 0, 140, 4, 0, 0, - 0, 2, 254, 255, 64, 4, + 208, 4, 0, 0, 44, 6, + 0, 0, 132, 6, 0, 0, + 65, 111, 110, 57, 152, 4, + 0, 0, 152, 4, 0, 0, + 0, 2, 254, 255, 76, 4, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -114,14 +114,14 @@ const BYTE BasicEffect_VSBasicTx[] = 4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 212, 0, 68, 66, 85, 71, + 215, 0, 68, 66, 85, 71, 40, 0, 0, 0, 36, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 15, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 232, 2, 0, 0, - 60, 1, 0, 0, 67, 58, + 60, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -133,7 +133,7 @@ const BYTE BasicEffect_VSBasicTx[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -148,26 +148,26 @@ const BYTE BasicEffect_VSBasicTx[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 88, 3, 0, 0, - 0, 0, 255, 255, 112, 3, + 255, 255, 100, 3, 0, 0, + 0, 0, 255, 255, 124, 3, 0, 0, 0, 0, 255, 255, - 124, 3, 0, 0, 43, 0, - 0, 0, 136, 3, 0, 0, - 14, 0, 0, 0, 152, 3, + 136, 3, 0, 0, 43, 0, + 0, 0, 148, 3, 0, 0, + 14, 0, 0, 0, 164, 3, 0, 0, 14, 0, 0, 0, - 168, 3, 0, 0, 14, 0, - 0, 0, 184, 3, 0, 0, - 43, 0, 0, 0, 200, 3, + 180, 3, 0, 0, 14, 0, + 0, 0, 196, 3, 0, 0, + 43, 0, 0, 0, 212, 3, 0, 0, 43, 0, 0, 0, - 216, 3, 0, 0, 43, 0, - 0, 0, 232, 3, 0, 0, - 96, 0, 1, 0, 248, 3, + 228, 3, 0, 0, 43, 0, + 0, 0, 244, 3, 0, 0, + 96, 0, 1, 0, 4, 4, 0, 0, 96, 0, 1, 0, - 12, 4, 0, 0, 44, 0, - 0, 0, 24, 4, 0, 0, - 45, 0, 0, 0, 36, 4, + 24, 4, 0, 0, 44, 0, + 0, 0, 36, 4, 0, 0, + 45, 0, 0, 0, 48, 4, 0, 0, 103, 0, 1, 0, - 48, 4, 0, 0, 86, 83, + 60, 4, 0, 0, 86, 83, 66, 97, 115, 105, 99, 84, 120, 0, 68, 105, 102, 102, 117, 115, 101, 0, 171, 171, @@ -255,7 +255,9 @@ const BYTE BasicEffect_VSBasicTx[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc index f26596b8..f0c26d0c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc @@ -41,20 +41,20 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSBasicTxNoFog<8> dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 110 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 110 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicTxNoFog<6,7> mov oPos.w, r0.z // ::VSBasicTxNoFog<9> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSBasicTxNoFog<0,1,2,3> -#line 117 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 117 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oT1.xy, v1 // ::VSBasicTxNoFog<4,5> // approximately 8 instruction slots used @@ -77,17 +77,17 @@ ret const BYTE BasicEffect_VSBasicTxNoFog[] = { - 68, 88, 66, 67, 148, 90, - 127, 101, 25, 225, 99, 199, - 163, 239, 33, 209, 36, 12, - 134, 83, 1, 0, 0, 0, - 0, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 255, 12, + 188, 102, 163, 51, 169, 182, + 7, 71, 195, 242, 239, 240, + 76, 213, 1, 0, 0, 0, + 12, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 36, 4, 0, 0, 52, 5, - 0, 0, 140, 5, 0, 0, - 65, 111, 110, 57, 236, 3, - 0, 0, 236, 3, 0, 0, - 0, 2, 254, 255, 172, 3, + 48, 4, 0, 0, 64, 5, + 0, 0, 152, 5, 0, 0, + 65, 111, 110, 57, 248, 3, + 0, 0, 248, 3, 0, 0, + 0, 2, 254, 255, 184, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -98,14 +98,14 @@ const BYTE BasicEffect_VSBasicTxNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 196, 0, 68, 66, 85, 71, + 199, 0, 68, 66, 85, 71, 40, 0, 0, 0, 228, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 10, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 168, 2, 0, 0, - 20, 1, 0, 0, 67, 58, + 20, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -117,7 +117,7 @@ const BYTE BasicEffect_VSBasicTxNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -132,19 +132,19 @@ const BYTE BasicEffect_VSBasicTxNoFog[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 24, 3, 0, 0, - 0, 0, 255, 255, 36, 3, + 255, 255, 36, 3, 0, 0, + 0, 0, 255, 255, 48, 3, 0, 0, 43, 0, 0, 0, - 48, 3, 0, 0, 43, 0, - 0, 0, 64, 3, 0, 0, - 43, 0, 0, 0, 80, 3, + 60, 3, 0, 0, 43, 0, + 0, 0, 76, 3, 0, 0, + 43, 0, 0, 0, 92, 3, 0, 0, 43, 0, 0, 0, - 96, 3, 0, 0, 110, 0, - 1, 0, 112, 3, 0, 0, - 110, 0, 1, 0, 132, 3, + 108, 3, 0, 0, 110, 0, + 1, 0, 124, 3, 0, 0, + 110, 0, 1, 0, 144, 3, 0, 0, 44, 0, 0, 0, - 144, 3, 0, 0, 117, 0, - 1, 0, 156, 3, 0, 0, + 156, 3, 0, 0, 117, 0, + 1, 0, 168, 3, 0, 0, 86, 83, 66, 97, 115, 105, 99, 84, 120, 78, 111, 70, 111, 103, 0, 68, 105, 102, @@ -228,7 +228,9 @@ const BYTE BasicEffect_VSBasicTxNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc index 3bd014fe..1c1db7a4 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc @@ -46,7 +46,7 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7,8,9> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSBasicTxVc<12> #line 14 @@ -54,22 +54,22 @@ max r0.x, r0.x, c7.x min oT1.w, r0.x, c7.y // ::VSBasicTxVc<7> -#line 132 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 132 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0, v2, c1 // ::VSBasicTxVc<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c3 // ::vout<0> dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 124 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 124 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicTxVc<10,11> mov oPos.w, r0.z // ::VSBasicTxVc<13> -#line 45 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 45 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT1.xyz, c7.x // ::VSBasicTxVc<4,5,6> -#line 131 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 131 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oT2.xy, v1 // ::VSBasicTxVc<8,9> // approximately 12 instruction slots used @@ -96,17 +96,17 @@ ret const BYTE BasicEffect_VSBasicTxVc[] = { - 68, 88, 66, 67, 109, 189, - 219, 132, 177, 108, 140, 212, - 39, 208, 246, 167, 198, 130, - 87, 85, 1, 0, 0, 0, - 100, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 68, 133, + 197, 228, 74, 239, 57, 21, + 82, 214, 247, 187, 233, 150, + 192, 162, 1, 0, 0, 0, + 112, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 244, 4, 0, 0, 100, 6, - 0, 0, 216, 6, 0, 0, - 65, 111, 110, 57, 188, 4, - 0, 0, 188, 4, 0, 0, - 0, 2, 254, 255, 112, 4, + 0, 5, 0, 0, 112, 6, + 0, 0, 228, 6, 0, 0, + 65, 111, 110, 57, 200, 4, + 0, 0, 200, 4, 0, 0, + 0, 2, 254, 255, 124, 4, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -119,14 +119,14 @@ const BYTE BasicEffect_VSBasicTxVc[] = 4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 220, 0, 68, 66, 85, 71, + 223, 0, 68, 66, 85, 71, 40, 0, 0, 0, 68, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 16, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 8, 3, 0, 0, - 68, 1, 0, 0, 67, 58, + 68, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -138,7 +138,7 @@ const BYTE BasicEffect_VSBasicTxVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -153,27 +153,27 @@ const BYTE BasicEffect_VSBasicTxVc[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 120, 3, 0, 0, - 0, 0, 255, 255, 144, 3, + 255, 255, 132, 3, 0, 0, + 0, 0, 255, 255, 156, 3, 0, 0, 0, 0, 255, 255, - 156, 3, 0, 0, 0, 0, - 255, 255, 168, 3, 0, 0, - 43, 0, 0, 0, 180, 3, + 168, 3, 0, 0, 0, 0, + 255, 255, 180, 3, 0, 0, + 43, 0, 0, 0, 192, 3, 0, 0, 14, 0, 0, 0, - 196, 3, 0, 0, 14, 0, - 0, 0, 212, 3, 0, 0, - 14, 0, 0, 0, 228, 3, + 208, 3, 0, 0, 14, 0, + 0, 0, 224, 3, 0, 0, + 14, 0, 0, 0, 240, 3, 0, 0, 132, 0, 1, 0, - 244, 3, 0, 0, 43, 0, - 0, 0, 4, 4, 0, 0, - 43, 0, 0, 0, 20, 4, + 0, 4, 0, 0, 43, 0, + 0, 0, 16, 4, 0, 0, + 43, 0, 0, 0, 32, 4, 0, 0, 43, 0, 0, 0, - 36, 4, 0, 0, 124, 0, - 1, 0, 52, 4, 0, 0, - 124, 0, 1, 0, 72, 4, + 48, 4, 0, 0, 124, 0, + 1, 0, 64, 4, 0, 0, + 124, 0, 1, 0, 84, 4, 0, 0, 45, 0, 0, 0, - 84, 4, 0, 0, 131, 0, - 1, 0, 96, 4, 0, 0, + 96, 4, 0, 0, 131, 0, + 1, 0, 108, 4, 0, 0, 86, 83, 66, 97, 115, 105, 99, 84, 120, 86, 99, 0, 68, 105, 102, 102, 117, 115, @@ -265,7 +265,9 @@ const BYTE BasicEffect_VSBasicTxVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc index dba8cae3..88f81644 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc @@ -43,18 +43,18 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7,8,9> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSBasicTxVcNoFog<8> -#line 147 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 147 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0, v2, c1 // ::VSBasicTxVcNoFog<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 139 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 139 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicTxVcNoFog<6,7> mov oPos.w, r0.z // ::VSBasicTxVcNoFog<9> @@ -82,17 +82,17 @@ ret const BYTE BasicEffect_VSBasicTxVcNoFog[] = { - 68, 88, 66, 67, 112, 14, - 119, 224, 77, 52, 152, 85, - 165, 175, 51, 107, 77, 138, - 61, 103, 1, 0, 0, 0, - 100, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 65, 63, + 168, 221, 255, 201, 37, 12, + 19, 194, 4, 98, 60, 73, + 38, 168, 1, 0, 0, 0, + 112, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 88, 4, 0, 0, 124, 5, - 0, 0, 240, 5, 0, 0, - 65, 111, 110, 57, 32, 4, - 0, 0, 32, 4, 0, 0, - 0, 2, 254, 255, 224, 3, + 100, 4, 0, 0, 136, 5, + 0, 0, 252, 5, 0, 0, + 65, 111, 110, 57, 44, 4, + 0, 0, 44, 4, 0, 0, + 0, 2, 254, 255, 236, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -103,14 +103,14 @@ const BYTE BasicEffect_VSBasicTxVcNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 205, 0, 68, 66, 85, 71, + 208, 0, 68, 66, 85, 71, 40, 0, 0, 0, 8, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 11, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 204, 2, 0, 0, - 28, 1, 0, 0, 67, 58, + 28, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -122,7 +122,7 @@ const BYTE BasicEffect_VSBasicTxVcNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -137,20 +137,20 @@ const BYTE BasicEffect_VSBasicTxVcNoFog[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 60, 3, 0, 0, - 0, 0, 255, 255, 72, 3, + 255, 255, 72, 3, 0, 0, + 0, 0, 255, 255, 84, 3, 0, 0, 0, 0, 255, 255, - 84, 3, 0, 0, 43, 0, - 0, 0, 96, 3, 0, 0, - 147, 0, 1, 0, 112, 3, + 96, 3, 0, 0, 43, 0, + 0, 0, 108, 3, 0, 0, + 147, 0, 1, 0, 124, 3, 0, 0, 43, 0, 0, 0, - 128, 3, 0, 0, 43, 0, - 0, 0, 144, 3, 0, 0, - 43, 0, 0, 0, 160, 3, + 140, 3, 0, 0, 43, 0, + 0, 0, 156, 3, 0, 0, + 43, 0, 0, 0, 172, 3, 0, 0, 139, 0, 1, 0, - 176, 3, 0, 0, 139, 0, - 1, 0, 196, 3, 0, 0, - 146, 0, 1, 0, 208, 3, + 188, 3, 0, 0, 139, 0, + 1, 0, 208, 3, 0, 0, + 146, 0, 1, 0, 220, 3, 0, 0, 86, 83, 66, 97, 115, 105, 99, 84, 120, 86, 99, 78, 111, 70, 111, 103, @@ -239,7 +239,9 @@ const BYTE BasicEffect_VSBasicTxVcNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc index f0802d44..d1f09681 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc @@ -43,7 +43,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5,6,7> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSBasicVc<10> #line 14 @@ -51,19 +51,19 @@ max r0.x, r0.x, c7.x min oT1.w, r0.x, c7.y // ::VSBasicVc<7> -#line 75 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 75 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0, v1, c1 // ::VSBasicVc<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c3 // ::vout<0> dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 68 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 68 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVc<8,9> mov oPos.w, r0.z // ::VSBasicVc<11> -#line 45 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 45 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT1.xyz, c7.x // ::VSBasicVc<4,5,6> // approximately 11 instruction slots used @@ -87,17 +87,17 @@ ret const BYTE BasicEffect_VSBasicVc[] = { - 68, 88, 66, 67, 158, 216, - 189, 127, 247, 201, 236, 51, - 146, 197, 0, 108, 49, 8, - 231, 40, 1, 0, 0, 0, - 140, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 205, 162, + 192, 131, 229, 144, 147, 105, + 81, 163, 119, 72, 22, 122, + 2, 66, 1, 0, 0, 0, + 152, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 136, 4, 0, 0, 204, 5, - 0, 0, 32, 6, 0, 0, - 65, 111, 110, 57, 80, 4, - 0, 0, 80, 4, 0, 0, - 0, 2, 254, 255, 4, 4, + 148, 4, 0, 0, 216, 5, + 0, 0, 44, 6, 0, 0, + 65, 111, 110, 57, 92, 4, + 0, 0, 92, 4, 0, 0, + 0, 2, 254, 255, 16, 4, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -110,14 +110,14 @@ const BYTE BasicEffect_VSBasicVc[] = 4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 199, 0, 68, 66, 85, 71, + 202, 0, 68, 66, 85, 71, 40, 0, 0, 0, 240, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 14, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 180, 2, 0, 0, - 52, 1, 0, 0, 67, 58, + 52, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -129,7 +129,7 @@ const BYTE BasicEffect_VSBasicVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -144,24 +144,24 @@ const BYTE BasicEffect_VSBasicVc[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 36, 3, 0, 0, - 0, 0, 255, 255, 60, 3, + 255, 255, 48, 3, 0, 0, + 0, 0, 255, 255, 72, 3, 0, 0, 0, 0, 255, 255, - 72, 3, 0, 0, 43, 0, - 0, 0, 84, 3, 0, 0, - 14, 0, 0, 0, 100, 3, + 84, 3, 0, 0, 43, 0, + 0, 0, 96, 3, 0, 0, + 14, 0, 0, 0, 112, 3, 0, 0, 14, 0, 0, 0, - 116, 3, 0, 0, 14, 0, - 0, 0, 132, 3, 0, 0, - 75, 0, 1, 0, 148, 3, + 128, 3, 0, 0, 14, 0, + 0, 0, 144, 3, 0, 0, + 75, 0, 1, 0, 160, 3, 0, 0, 43, 0, 0, 0, - 164, 3, 0, 0, 43, 0, - 0, 0, 180, 3, 0, 0, - 43, 0, 0, 0, 196, 3, + 176, 3, 0, 0, 43, 0, + 0, 0, 192, 3, 0, 0, + 43, 0, 0, 0, 208, 3, 0, 0, 68, 0, 1, 0, - 212, 3, 0, 0, 68, 0, - 1, 0, 232, 3, 0, 0, - 45, 0, 0, 0, 244, 3, + 224, 3, 0, 0, 68, 0, + 1, 0, 244, 3, 0, 0, + 45, 0, 0, 0, 0, 4, 0, 0, 86, 83, 66, 97, 115, 105, 99, 86, 99, 0, 68, 105, 102, 102, 117, 115, @@ -242,7 +242,9 @@ const BYTE BasicEffect_VSBasicVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc index dfe64c9b..8aecebee 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc @@ -40,18 +40,18 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5,6,7> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSBasicVcNoFog<6> -#line 89 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 89 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0, v1, c1 // ::VSBasicVcNoFog<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 82 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 82 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVcNoFog<4,5> mov oPos.w, r0.z // ::VSBasicVcNoFog<7> @@ -73,17 +73,17 @@ ret const BYTE BasicEffect_VSBasicVcNoFog[] = { - 68, 88, 66, 67, 114, 65, - 2, 27, 167, 13, 188, 197, - 210, 128, 13, 198, 110, 181, - 26, 207, 1, 0, 0, 0, - 136, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 118, 186, + 204, 183, 153, 192, 108, 157, + 160, 150, 243, 26, 75, 106, + 171, 221, 1, 0, 0, 0, + 148, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 232, 3, 0, 0, 224, 4, - 0, 0, 52, 5, 0, 0, - 65, 111, 110, 57, 176, 3, - 0, 0, 176, 3, 0, 0, - 0, 2, 254, 255, 112, 3, + 244, 3, 0, 0, 236, 4, + 0, 0, 64, 5, 0, 0, + 65, 111, 110, 57, 188, 3, + 0, 0, 188, 3, 0, 0, + 0, 2, 254, 255, 124, 3, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -94,14 +94,14 @@ const BYTE BasicEffect_VSBasicVcNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 183, 0, 68, 66, 85, 71, + 186, 0, 68, 66, 85, 71, 40, 0, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 9, 0, 0, 0, 196, 0, 0, 0, 3, 0, 0, 0, 116, 2, 0, 0, - 12, 1, 0, 0, 67, 58, + 12, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -113,7 +113,7 @@ const BYTE BasicEffect_VSBasicVcNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -128,18 +128,18 @@ const BYTE BasicEffect_VSBasicVcNoFog[] = 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 255, 255, 228, 2, 0, 0, - 0, 0, 255, 255, 240, 2, + 255, 255, 240, 2, 0, 0, + 0, 0, 255, 255, 252, 2, 0, 0, 43, 0, 0, 0, - 252, 2, 0, 0, 89, 0, - 1, 0, 12, 3, 0, 0, - 43, 0, 0, 0, 28, 3, + 8, 3, 0, 0, 89, 0, + 1, 0, 24, 3, 0, 0, + 43, 0, 0, 0, 40, 3, 0, 0, 43, 0, 0, 0, - 44, 3, 0, 0, 43, 0, - 0, 0, 60, 3, 0, 0, - 82, 0, 1, 0, 76, 3, + 56, 3, 0, 0, 43, 0, + 0, 0, 72, 3, 0, 0, + 82, 0, 1, 0, 88, 3, 0, 0, 82, 0, 1, 0, - 96, 3, 0, 0, 86, 83, + 108, 3, 0, 0, 86, 83, 66, 97, 115, 105, 99, 86, 99, 78, 111, 70, 111, 103, 0, 68, 105, 102, 102, 117, @@ -216,7 +216,9 @@ const BYTE BasicEffect_VSBasicVcNoFog[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc index 084bf7f6..f5bea02e 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc @@ -43,7 +43,7 @@ dcl_texcoord v0 // vin<0,1,2,3> dcl_texcoord1 v1 // vin<4,5,6> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, v1, c18 dp3 r0.y, v1, c19 dp3 r0.z, v1, c20 @@ -113,21 +113,21 @@ #line 63 dp4 oPos.z, v0, c23 // ::VSBasicVertexLighting<10> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c14 max r0.x, r0.x, c25.x min oT1.w, r0.x, c25.y // ::VSBasicVertexLighting<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c21 // ::vout<0> dp4 r0.y, v0, c22 // ::vout<1> dp4 r0.z, v0, c24 // ::vout<3> -#line 154 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 154 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVertexLighting<8,9> mov oPos.w, r0.z // ::VSBasicVertexLighting<11> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c1.w // ::VSBasicVertexLighting<3> // approximately 61 instruction slots used @@ -197,17 +197,17 @@ ret const BYTE BasicEffect_VSBasicVertexLighting[] = { - 68, 88, 66, 67, 11, 169, - 156, 99, 25, 253, 36, 15, - 116, 176, 152, 41, 101, 109, - 158, 51, 1, 0, 0, 0, - 104, 18, 0, 0, 4, 0, + 68, 88, 66, 67, 10, 186, + 222, 200, 42, 197, 147, 26, + 191, 48, 1, 228, 38, 201, + 218, 35, 1, 0, 0, 0, + 116, 18, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 216, 10, 0, 0, 168, 17, - 0, 0, 252, 17, 0, 0, - 65, 111, 110, 57, 160, 10, - 0, 0, 160, 10, 0, 0, - 0, 2, 254, 255, 84, 10, + 228, 10, 0, 0, 180, 17, + 0, 0, 8, 18, 0, 0, + 65, 111, 110, 57, 172, 10, + 0, 0, 172, 10, 0, 0, + 0, 2, 254, 255, 96, 10, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -220,14 +220,14 @@ const BYTE BasicEffect_VSBasicVertexLighting[] = 7, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 194, 1, 68, 66, 85, 71, + 197, 1, 68, 66, 85, 71, 40, 0, 0, 0, 220, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 54, 0, 0, 0, 16, 1, 0, 0, 13, 0, 0, 0, 216, 5, 0, 0, - 244, 2, 0, 0, 67, 58, + 244, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -239,7 +239,7 @@ const BYTE BasicEffect_VSBasicVertexLighting[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -251,7 +251,7 @@ const BYTE BasicEffect_VSBasicVertexLighting[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -267,77 +267,77 @@ const BYTE BasicEffect_VSBasicVertexLighting[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 16, 7, 0, 0, 0, 0, - 255, 255, 40, 7, 0, 0, - 0, 0, 255, 255, 52, 7, + 28, 7, 0, 0, 0, 0, + 255, 255, 52, 7, 0, 0, + 0, 0, 255, 255, 64, 7, 0, 0, 59, 0, 0, 0, - 64, 7, 0, 0, 59, 0, - 0, 0, 80, 7, 0, 0, - 59, 0, 0, 0, 96, 7, + 76, 7, 0, 0, 59, 0, + 0, 0, 92, 7, 0, 0, + 59, 0, 0, 0, 108, 7, 0, 0, 59, 0, 0, 0, - 112, 7, 0, 0, 36, 0, - 0, 0, 124, 7, 0, 0, - 36, 0, 0, 0, 140, 7, + 124, 7, 0, 0, 36, 0, + 0, 0, 136, 7, 0, 0, + 36, 0, 0, 0, 152, 7, 0, 0, 36, 0, 0, 0, - 156, 7, 0, 0, 39, 0, - 0, 0, 172, 7, 0, 0, - 41, 0, 0, 0, 188, 7, + 168, 7, 0, 0, 39, 0, + 0, 0, 184, 7, 0, 0, + 41, 0, 0, 0, 200, 7, 0, 0, 46, 0, 0, 0, - 204, 7, 0, 0, 46, 0, - 0, 0, 220, 7, 0, 0, - 46, 0, 0, 0, 240, 7, + 216, 7, 0, 0, 46, 0, + 0, 0, 232, 7, 0, 0, + 46, 0, 0, 0, 252, 7, 0, 0, 46, 0, 0, 0, - 4, 8, 0, 0, 46, 0, - 0, 0, 16, 8, 0, 0, - 57, 0, 0, 0, 36, 8, + 16, 8, 0, 0, 46, 0, + 0, 0, 28, 8, 0, 0, + 57, 0, 0, 0, 48, 8, 0, 0, 57, 0, 0, 0, - 52, 8, 0, 0, 57, 0, - 0, 0, 68, 8, 0, 0, - 58, 0, 0, 0, 84, 8, + 64, 8, 0, 0, 57, 0, + 0, 0, 80, 8, 0, 0, + 58, 0, 0, 0, 96, 8, 0, 0, 58, 0, 0, 0, - 100, 8, 0, 0, 33, 0, - 0, 0, 112, 8, 0, 0, - 33, 0, 0, 0, 128, 8, + 112, 8, 0, 0, 33, 0, + 0, 0, 124, 8, 0, 0, + 33, 0, 0, 0, 140, 8, 0, 0, 37, 0, 0, 0, - 140, 8, 0, 0, 33, 0, - 0, 0, 156, 8, 0, 0, - 33, 0, 0, 0, 172, 8, + 152, 8, 0, 0, 33, 0, + 0, 0, 168, 8, 0, 0, + 33, 0, 0, 0, 184, 8, 0, 0, 33, 0, 0, 0, - 188, 8, 0, 0, 37, 0, - 0, 0, 200, 8, 0, 0, - 33, 0, 0, 0, 216, 8, + 200, 8, 0, 0, 37, 0, + 0, 0, 212, 8, 0, 0, + 33, 0, 0, 0, 228, 8, 0, 0, 37, 0, 0, 0, - 228, 8, 0, 0, 42, 0, - 0, 0, 244, 8, 0, 0, - 42, 0, 0, 0, 4, 9, + 240, 8, 0, 0, 42, 0, + 0, 0, 0, 9, 0, 0, + 42, 0, 0, 0, 16, 9, 0, 0, 42, 0, 0, 0, - 20, 9, 0, 0, 42, 0, - 0, 0, 32, 9, 0, 0, - 42, 0, 0, 0, 44, 9, + 32, 9, 0, 0, 42, 0, + 0, 0, 44, 9, 0, 0, + 42, 0, 0, 0, 56, 9, 0, 0, 42, 0, 0, 0, - 56, 9, 0, 0, 42, 0, - 0, 0, 72, 9, 0, 0, - 42, 0, 0, 0, 84, 9, + 68, 9, 0, 0, 42, 0, + 0, 0, 84, 9, 0, 0, + 42, 0, 0, 0, 96, 9, 0, 0, 42, 0, 0, 0, - 96, 9, 0, 0, 47, 0, - 0, 0, 108, 9, 0, 0, - 47, 0, 0, 0, 124, 9, + 108, 9, 0, 0, 47, 0, + 0, 0, 120, 9, 0, 0, + 47, 0, 0, 0, 136, 9, 0, 0, 47, 0, 0, 0, - 144, 9, 0, 0, 47, 0, - 0, 0, 164, 9, 0, 0, - 63, 0, 0, 0, 180, 9, + 156, 9, 0, 0, 47, 0, + 0, 0, 176, 9, 0, 0, + 63, 0, 0, 0, 192, 9, 0, 0, 14, 0, 1, 0, - 196, 9, 0, 0, 14, 0, - 1, 0, 212, 9, 0, 0, - 14, 0, 1, 0, 228, 9, + 208, 9, 0, 0, 14, 0, + 1, 0, 224, 9, 0, 0, + 14, 0, 1, 0, 240, 9, 0, 0, 63, 0, 0, 0, - 244, 9, 0, 0, 63, 0, - 0, 0, 4, 10, 0, 0, - 63, 0, 0, 0, 20, 10, + 0, 10, 0, 0, 63, 0, + 0, 0, 16, 10, 0, 0, + 63, 0, 0, 0, 32, 10, 0, 0, 154, 0, 2, 0, - 36, 10, 0, 0, 154, 0, - 2, 0, 56, 10, 0, 0, - 46, 0, 0, 0, 68, 10, + 48, 10, 0, 0, 154, 0, + 2, 0, 68, 10, 0, 0, + 46, 0, 0, 0, 80, 10, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -520,7 +520,9 @@ const BYTE BasicEffect_VSBasicVertexLighting[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 25, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc index 512faba1..5648ff2c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc @@ -46,7 +46,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, v1, c18 dp3 r0.y, v1, c19 dp3 r0.z, v1, c20 @@ -116,24 +116,24 @@ #line 63 dp4 oPos.z, v0, c23 // ::VSBasicVertexLightingTx<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c14 max r0.x, r0.x, c25.x min oT1.w, r0.x, c25.y // ::VSBasicVertexLightingTx<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c21 // ::vout<0> dp4 r0.y, v0, c22 // ::vout<1> dp4 r0.z, v0, c24 // ::vout<3> -#line 180 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 180 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVertexLightingTx<10,11> mov oPos.w, r0.z // ::VSBasicVertexLightingTx<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c1.w // ::VSBasicVertexLightingTx<3> -#line 187 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 187 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mov oT2.xy, v2 // ::VSBasicVertexLightingTx<8,9> // approximately 62 instruction slots used @@ -206,17 +206,17 @@ ret const BYTE BasicEffect_VSBasicVertexLightingTx[] = { - 68, 88, 66, 67, 128, 152, - 53, 198, 172, 158, 146, 237, - 44, 232, 207, 138, 186, 159, - 64, 219, 1, 0, 0, 0, - 64, 19, 0, 0, 4, 0, + 68, 88, 66, 67, 219, 61, + 22, 200, 14, 147, 141, 147, + 12, 93, 201, 38, 94, 222, + 36, 141, 1, 0, 0, 0, + 76, 19, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 68, 11, 0, 0, 64, 18, - 0, 0, 180, 18, 0, 0, - 65, 111, 110, 57, 12, 11, - 0, 0, 12, 11, 0, 0, - 0, 2, 254, 255, 192, 10, + 80, 11, 0, 0, 76, 18, + 0, 0, 192, 18, 0, 0, + 65, 111, 110, 57, 24, 11, + 0, 0, 24, 11, 0, 0, + 0, 2, 254, 255, 204, 10, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -229,14 +229,14 @@ const BYTE BasicEffect_VSBasicVertexLightingTx[] = 7, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 215, 1, 68, 66, 85, 71, + 218, 1, 68, 66, 85, 71, 40, 0, 0, 0, 48, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 56, 0, 0, 0, 16, 1, 0, 0, 13, 0, 0, 0, 44, 6, 0, 0, - 4, 3, 0, 0, 67, 58, + 4, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -248,7 +248,7 @@ const BYTE BasicEffect_VSBasicVertexLightingTx[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -260,7 +260,7 @@ const BYTE BasicEffect_VSBasicVertexLightingTx[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -276,80 +276,80 @@ const BYTE BasicEffect_VSBasicVertexLightingTx[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 100, 7, 0, 0, 0, 0, - 255, 255, 124, 7, 0, 0, - 0, 0, 255, 255, 136, 7, + 112, 7, 0, 0, 0, 0, + 255, 255, 136, 7, 0, 0, + 0, 0, 255, 255, 148, 7, 0, 0, 0, 0, 255, 255, - 148, 7, 0, 0, 59, 0, - 0, 0, 160, 7, 0, 0, - 59, 0, 0, 0, 176, 7, + 160, 7, 0, 0, 59, 0, + 0, 0, 172, 7, 0, 0, + 59, 0, 0, 0, 188, 7, 0, 0, 59, 0, 0, 0, - 192, 7, 0, 0, 59, 0, - 0, 0, 208, 7, 0, 0, - 36, 0, 0, 0, 220, 7, + 204, 7, 0, 0, 59, 0, + 0, 0, 220, 7, 0, 0, + 36, 0, 0, 0, 232, 7, 0, 0, 36, 0, 0, 0, - 236, 7, 0, 0, 36, 0, - 0, 0, 252, 7, 0, 0, - 39, 0, 0, 0, 12, 8, + 248, 7, 0, 0, 36, 0, + 0, 0, 8, 8, 0, 0, + 39, 0, 0, 0, 24, 8, 0, 0, 41, 0, 0, 0, - 28, 8, 0, 0, 46, 0, - 0, 0, 44, 8, 0, 0, - 46, 0, 0, 0, 60, 8, + 40, 8, 0, 0, 46, 0, + 0, 0, 56, 8, 0, 0, + 46, 0, 0, 0, 72, 8, 0, 0, 46, 0, 0, 0, - 80, 8, 0, 0, 46, 0, - 0, 0, 100, 8, 0, 0, - 46, 0, 0, 0, 112, 8, + 92, 8, 0, 0, 46, 0, + 0, 0, 112, 8, 0, 0, + 46, 0, 0, 0, 124, 8, 0, 0, 57, 0, 0, 0, - 132, 8, 0, 0, 57, 0, - 0, 0, 148, 8, 0, 0, - 57, 0, 0, 0, 164, 8, + 144, 8, 0, 0, 57, 0, + 0, 0, 160, 8, 0, 0, + 57, 0, 0, 0, 176, 8, 0, 0, 58, 0, 0, 0, - 180, 8, 0, 0, 58, 0, - 0, 0, 196, 8, 0, 0, - 33, 0, 0, 0, 208, 8, + 192, 8, 0, 0, 58, 0, + 0, 0, 208, 8, 0, 0, + 33, 0, 0, 0, 220, 8, 0, 0, 33, 0, 0, 0, - 224, 8, 0, 0, 37, 0, - 0, 0, 236, 8, 0, 0, - 33, 0, 0, 0, 252, 8, + 236, 8, 0, 0, 37, 0, + 0, 0, 248, 8, 0, 0, + 33, 0, 0, 0, 8, 9, 0, 0, 33, 0, 0, 0, - 12, 9, 0, 0, 33, 0, - 0, 0, 28, 9, 0, 0, - 37, 0, 0, 0, 40, 9, + 24, 9, 0, 0, 33, 0, + 0, 0, 40, 9, 0, 0, + 37, 0, 0, 0, 52, 9, 0, 0, 33, 0, 0, 0, - 56, 9, 0, 0, 37, 0, - 0, 0, 68, 9, 0, 0, - 42, 0, 0, 0, 84, 9, + 68, 9, 0, 0, 37, 0, + 0, 0, 80, 9, 0, 0, + 42, 0, 0, 0, 96, 9, 0, 0, 42, 0, 0, 0, - 100, 9, 0, 0, 42, 0, - 0, 0, 116, 9, 0, 0, - 42, 0, 0, 0, 128, 9, + 112, 9, 0, 0, 42, 0, + 0, 0, 128, 9, 0, 0, + 42, 0, 0, 0, 140, 9, 0, 0, 42, 0, 0, 0, - 140, 9, 0, 0, 42, 0, - 0, 0, 152, 9, 0, 0, - 42, 0, 0, 0, 168, 9, + 152, 9, 0, 0, 42, 0, + 0, 0, 164, 9, 0, 0, + 42, 0, 0, 0, 180, 9, 0, 0, 42, 0, 0, 0, - 180, 9, 0, 0, 42, 0, - 0, 0, 192, 9, 0, 0, - 47, 0, 0, 0, 204, 9, + 192, 9, 0, 0, 42, 0, + 0, 0, 204, 9, 0, 0, + 47, 0, 0, 0, 216, 9, 0, 0, 47, 0, 0, 0, - 220, 9, 0, 0, 47, 0, - 0, 0, 240, 9, 0, 0, - 47, 0, 0, 0, 4, 10, + 232, 9, 0, 0, 47, 0, + 0, 0, 252, 9, 0, 0, + 47, 0, 0, 0, 16, 10, 0, 0, 63, 0, 0, 0, - 20, 10, 0, 0, 14, 0, - 1, 0, 36, 10, 0, 0, - 14, 0, 1, 0, 52, 10, + 32, 10, 0, 0, 14, 0, + 1, 0, 48, 10, 0, 0, + 14, 0, 1, 0, 64, 10, 0, 0, 14, 0, 1, 0, - 68, 10, 0, 0, 63, 0, - 0, 0, 84, 10, 0, 0, - 63, 0, 0, 0, 100, 10, + 80, 10, 0, 0, 63, 0, + 0, 0, 96, 10, 0, 0, + 63, 0, 0, 0, 112, 10, 0, 0, 63, 0, 0, 0, - 116, 10, 0, 0, 180, 0, - 2, 0, 132, 10, 0, 0, - 180, 0, 2, 0, 152, 10, + 128, 10, 0, 0, 180, 0, + 2, 0, 144, 10, 0, 0, + 180, 0, 2, 0, 164, 10, 0, 0, 46, 0, 0, 0, - 164, 10, 0, 0, 187, 0, - 2, 0, 176, 10, 0, 0, + 176, 10, 0, 0, 187, 0, + 2, 0, 188, 10, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -543,7 +543,9 @@ const BYTE BasicEffect_VSBasicVertexLightingTx[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 25, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc index 183879a2..f38eb6f9 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc @@ -48,7 +48,7 @@ dcl_texcoord2 v2 // vin<7,8> dcl_texcoord3 v3 // vin<9,10,11,12> -#line 57 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 57 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::pos_ws<0> dp4 r0.y, v0, c16 // ::pos_ws<1> dp4 r0.z, v0, c17 // ::pos_ws<2> @@ -115,28 +115,28 @@ #line 63 dp4 oPos.z, v0, c23 // ::VSBasicVertexLightingTxVc<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c14 max r0.x, r0.x, c25.x min oT1.w, r0.x, c25.y // ::VSBasicVertexLightingTxVc<7> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mul r0.xyz, r1.y, c8 mad r0.xyz, r1.x, c7, r0 mad r0.xyz, r1.z, c9, r0 mov r1.xyz, c1 // Parameters::DiffuseColor<0,1,2> mad r0.xyz, r0, r1, c2 // ::result<0,1,2> -#line 202 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 202 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.xyz, r0, v3 // ::VSBasicVertexLightingTxVc<0,1,2> mul oT0.w, v3.w, c1.w // ::VSBasicVertexLightingTxVc<3> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c21 // ::vout<0> dp4 r0.y, v0, c22 // ::vout<1> dp4 r0.z, v0, c24 // ::vout<3> -#line 194 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 194 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVertexLightingTxVc<10,11> mov oPos.w, r0.z // ::VSBasicVertexLightingTxVc<13> @@ -215,17 +215,17 @@ ret const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = { - 68, 88, 66, 67, 210, 196, - 69, 235, 174, 230, 252, 142, - 74, 169, 9, 49, 0, 169, - 138, 236, 1, 0, 0, 0, - 40, 20, 0, 0, 4, 0, + 68, 88, 66, 67, 75, 168, + 173, 205, 115, 230, 212, 135, + 251, 144, 45, 145, 83, 86, + 65, 26, 1, 0, 0, 0, + 52, 20, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 220, 11, 0, 0, 8, 19, - 0, 0, 156, 19, 0, 0, - 65, 111, 110, 57, 164, 11, - 0, 0, 164, 11, 0, 0, - 0, 2, 254, 255, 88, 11, + 232, 11, 0, 0, 20, 19, + 0, 0, 168, 19, 0, 0, + 65, 111, 110, 57, 176, 11, + 0, 0, 176, 11, 0, 0, + 0, 2, 254, 255, 100, 11, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -238,14 +238,14 @@ const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = 7, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 245, 1, 68, 66, 85, 71, + 248, 1, 68, 66, 85, 71, 40, 0, 0, 0, 168, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 58, 0, 0, 0, 16, 1, 0, 0, 14, 0, 0, 0, 144, 6, 0, 0, - 20, 3, 0, 0, 67, 58, + 20, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -257,7 +257,7 @@ const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -269,7 +269,7 @@ const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -285,83 +285,83 @@ const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 220, 7, 0, 0, 0, 0, - 255, 255, 244, 7, 0, 0, - 0, 0, 255, 255, 0, 8, + 232, 7, 0, 0, 0, 0, + 255, 255, 0, 8, 0, 0, + 0, 0, 255, 255, 12, 8, 0, 0, 0, 0, 255, 255, - 12, 8, 0, 0, 0, 0, - 255, 255, 24, 8, 0, 0, - 57, 0, 0, 0, 36, 8, + 24, 8, 0, 0, 0, 0, + 255, 255, 36, 8, 0, 0, + 57, 0, 0, 0, 48, 8, 0, 0, 57, 0, 0, 0, - 52, 8, 0, 0, 57, 0, - 0, 0, 68, 8, 0, 0, - 58, 0, 0, 0, 84, 8, + 64, 8, 0, 0, 57, 0, + 0, 0, 80, 8, 0, 0, + 58, 0, 0, 0, 96, 8, 0, 0, 58, 0, 0, 0, - 100, 8, 0, 0, 33, 0, - 0, 0, 112, 8, 0, 0, - 33, 0, 0, 0, 128, 8, + 112, 8, 0, 0, 33, 0, + 0, 0, 124, 8, 0, 0, + 33, 0, 0, 0, 140, 8, 0, 0, 59, 0, 0, 0, - 140, 8, 0, 0, 59, 0, - 0, 0, 156, 8, 0, 0, - 59, 0, 0, 0, 172, 8, + 152, 8, 0, 0, 59, 0, + 0, 0, 168, 8, 0, 0, + 59, 0, 0, 0, 184, 8, 0, 0, 59, 0, 0, 0, - 188, 8, 0, 0, 37, 0, - 0, 0, 200, 8, 0, 0, - 33, 0, 0, 0, 216, 8, + 200, 8, 0, 0, 37, 0, + 0, 0, 212, 8, 0, 0, + 33, 0, 0, 0, 228, 8, 0, 0, 33, 0, 0, 0, - 232, 8, 0, 0, 33, 0, - 0, 0, 248, 8, 0, 0, - 37, 0, 0, 0, 4, 9, + 244, 8, 0, 0, 33, 0, + 0, 0, 4, 9, 0, 0, + 37, 0, 0, 0, 16, 9, 0, 0, 33, 0, 0, 0, - 20, 9, 0, 0, 37, 0, - 0, 0, 32, 9, 0, 0, - 42, 0, 0, 0, 48, 9, + 32, 9, 0, 0, 37, 0, + 0, 0, 44, 9, 0, 0, + 42, 0, 0, 0, 60, 9, 0, 0, 36, 0, 0, 0, - 64, 9, 0, 0, 36, 0, - 0, 0, 80, 9, 0, 0, - 36, 0, 0, 0, 96, 9, + 76, 9, 0, 0, 36, 0, + 0, 0, 92, 9, 0, 0, + 36, 0, 0, 0, 108, 9, 0, 0, 39, 0, 0, 0, - 112, 9, 0, 0, 41, 0, - 0, 0, 128, 9, 0, 0, - 42, 0, 0, 0, 144, 9, + 124, 9, 0, 0, 41, 0, + 0, 0, 140, 9, 0, 0, + 42, 0, 0, 0, 156, 9, 0, 0, 42, 0, 0, 0, - 160, 9, 0, 0, 42, 0, - 0, 0, 172, 9, 0, 0, - 42, 0, 0, 0, 184, 9, + 172, 9, 0, 0, 42, 0, + 0, 0, 184, 9, 0, 0, + 42, 0, 0, 0, 196, 9, 0, 0, 42, 0, 0, 0, - 196, 9, 0, 0, 42, 0, - 0, 0, 212, 9, 0, 0, - 47, 0, 0, 0, 224, 9, + 208, 9, 0, 0, 42, 0, + 0, 0, 224, 9, 0, 0, + 47, 0, 0, 0, 236, 9, 0, 0, 42, 0, 0, 0, - 240, 9, 0, 0, 42, 0, - 0, 0, 252, 9, 0, 0, - 47, 0, 0, 0, 8, 10, + 252, 9, 0, 0, 42, 0, + 0, 0, 8, 10, 0, 0, + 47, 0, 0, 0, 20, 10, 0, 0, 47, 0, 0, 0, - 28, 10, 0, 0, 47, 0, - 0, 0, 48, 10, 0, 0, - 63, 0, 0, 0, 64, 10, + 40, 10, 0, 0, 47, 0, + 0, 0, 60, 10, 0, 0, + 63, 0, 0, 0, 76, 10, 0, 0, 14, 0, 1, 0, - 80, 10, 0, 0, 14, 0, - 1, 0, 96, 10, 0, 0, - 14, 0, 1, 0, 112, 10, + 92, 10, 0, 0, 14, 0, + 1, 0, 108, 10, 0, 0, + 14, 0, 1, 0, 124, 10, 0, 0, 46, 0, 0, 0, - 128, 10, 0, 0, 46, 0, - 0, 0, 144, 10, 0, 0, - 46, 0, 0, 0, 164, 10, + 140, 10, 0, 0, 46, 0, + 0, 0, 156, 10, 0, 0, + 46, 0, 0, 0, 176, 10, 0, 0, 46, 0, 0, 0, - 184, 10, 0, 0, 46, 0, - 0, 0, 196, 10, 0, 0, - 202, 0, 2, 0, 216, 10, + 196, 10, 0, 0, 46, 0, + 0, 0, 208, 10, 0, 0, + 202, 0, 2, 0, 228, 10, 0, 0, 202, 0, 2, 0, - 232, 10, 0, 0, 63, 0, - 0, 0, 248, 10, 0, 0, - 63, 0, 0, 0, 8, 11, + 244, 10, 0, 0, 63, 0, + 0, 0, 4, 11, 0, 0, + 63, 0, 0, 0, 20, 11, 0, 0, 63, 0, 0, 0, - 24, 11, 0, 0, 194, 0, - 2, 0, 40, 11, 0, 0, - 194, 0, 2, 0, 60, 11, + 36, 11, 0, 0, 194, 0, + 2, 0, 52, 11, 0, 0, + 194, 0, 2, 0, 72, 11, 0, 0, 201, 0, 2, 0, - 72, 11, 0, 0, 80, 97, + 84, 11, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, 67, 111, @@ -572,7 +572,9 @@ const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 25, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc index f8590887..7baa43b1 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc @@ -45,7 +45,7 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8,9,10> -#line 57 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 57 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c15 // ::pos_ws<0> dp4 r0.y, v0, c16 // ::pos_ws<1> dp4 r0.z, v0, c17 // ::pos_ws<2> @@ -112,28 +112,28 @@ #line 63 dp4 oPos.z, v0, c23 // ::VSBasicVertexLightingVc<10> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c14 max r0.x, r0.x, c25.x min oT1.w, r0.x, c25.y // ::VSBasicVertexLightingVc<7> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mul r0.xyz, r1.y, c8 mad r0.xyz, r1.x, c7, r0 mad r0.xyz, r1.z, c9, r0 mov r1.xyz, c1 // Parameters::DiffuseColor<0,1,2> mad r0.xyz, r0, r1, c2 // ::result<0,1,2> -#line 173 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 173 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mul oT0.xyz, r0, v2 // ::VSBasicVertexLightingVc<0,1,2> mul oT0.w, v2.w, c1.w // ::VSBasicVertexLightingVc<3> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, v0, c21 // ::vout<0> dp4 r0.y, v0, c22 // ::vout<1> dp4 r0.z, v0, c24 // ::vout<3> -#line 166 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" +#line 166 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\BasicEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSBasicVertexLightingVc<8,9> mov oPos.w, r0.z // ::VSBasicVertexLightingVc<11> @@ -206,17 +206,17 @@ ret const BYTE BasicEffect_VSBasicVertexLightingVc[] = { - 68, 88, 66, 67, 226, 181, - 114, 107, 244, 208, 151, 98, - 45, 197, 123, 238, 12, 60, - 225, 221, 1, 0, 0, 0, - 76, 19, 0, 0, 4, 0, + 68, 88, 66, 67, 78, 15, + 26, 9, 203, 147, 125, 21, + 227, 123, 102, 242, 107, 110, + 178, 93, 1, 0, 0, 0, + 88, 19, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 108, 11, 0, 0, 108, 18, - 0, 0, 224, 18, 0, 0, - 65, 111, 110, 57, 52, 11, - 0, 0, 52, 11, 0, 0, - 0, 2, 254, 255, 232, 10, + 120, 11, 0, 0, 120, 18, + 0, 0, 236, 18, 0, 0, + 65, 111, 110, 57, 64, 11, + 0, 0, 64, 11, 0, 0, + 0, 2, 254, 255, 244, 10, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -229,14 +229,14 @@ const BYTE BasicEffect_VSBasicVertexLightingVc[] = 7, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 223, 1, 68, 66, 85, 71, + 226, 1, 68, 66, 85, 71, 40, 0, 0, 0, 80, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 0, 0, 56, 0, 0, 0, 16, 1, 0, 0, 14, 0, 0, 0, 56, 6, 0, 0, - 4, 3, 0, 0, 67, 58, + 4, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -248,7 +248,7 @@ const BYTE BasicEffect_VSBasicVertexLightingVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -260,7 +260,7 @@ const BYTE BasicEffect_VSBasicVertexLightingVc[] = 114, 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -276,80 +276,80 @@ const BYTE BasicEffect_VSBasicVertexLightingVc[] = 0, 171, 40, 0, 0, 0, 113, 0, 0, 0, 184, 0, 0, 0, 0, 0, 255, 255, - 132, 7, 0, 0, 0, 0, - 255, 255, 156, 7, 0, 0, - 0, 0, 255, 255, 168, 7, + 144, 7, 0, 0, 0, 0, + 255, 255, 168, 7, 0, 0, + 0, 0, 255, 255, 180, 7, 0, 0, 0, 0, 255, 255, - 180, 7, 0, 0, 57, 0, - 0, 0, 192, 7, 0, 0, - 57, 0, 0, 0, 208, 7, + 192, 7, 0, 0, 57, 0, + 0, 0, 204, 7, 0, 0, + 57, 0, 0, 0, 220, 7, 0, 0, 57, 0, 0, 0, - 224, 7, 0, 0, 58, 0, - 0, 0, 240, 7, 0, 0, - 58, 0, 0, 0, 0, 8, + 236, 7, 0, 0, 58, 0, + 0, 0, 252, 7, 0, 0, + 58, 0, 0, 0, 12, 8, 0, 0, 33, 0, 0, 0, - 12, 8, 0, 0, 33, 0, - 0, 0, 28, 8, 0, 0, - 59, 0, 0, 0, 40, 8, + 24, 8, 0, 0, 33, 0, + 0, 0, 40, 8, 0, 0, + 59, 0, 0, 0, 52, 8, 0, 0, 59, 0, 0, 0, - 56, 8, 0, 0, 59, 0, - 0, 0, 72, 8, 0, 0, - 59, 0, 0, 0, 88, 8, + 68, 8, 0, 0, 59, 0, + 0, 0, 84, 8, 0, 0, + 59, 0, 0, 0, 100, 8, 0, 0, 37, 0, 0, 0, - 100, 8, 0, 0, 33, 0, - 0, 0, 116, 8, 0, 0, - 33, 0, 0, 0, 132, 8, + 112, 8, 0, 0, 33, 0, + 0, 0, 128, 8, 0, 0, + 33, 0, 0, 0, 144, 8, 0, 0, 33, 0, 0, 0, - 148, 8, 0, 0, 37, 0, - 0, 0, 160, 8, 0, 0, - 33, 0, 0, 0, 176, 8, + 160, 8, 0, 0, 37, 0, + 0, 0, 172, 8, 0, 0, + 33, 0, 0, 0, 188, 8, 0, 0, 37, 0, 0, 0, - 188, 8, 0, 0, 42, 0, - 0, 0, 204, 8, 0, 0, - 36, 0, 0, 0, 220, 8, + 200, 8, 0, 0, 42, 0, + 0, 0, 216, 8, 0, 0, + 36, 0, 0, 0, 232, 8, 0, 0, 36, 0, 0, 0, - 236, 8, 0, 0, 36, 0, - 0, 0, 252, 8, 0, 0, - 39, 0, 0, 0, 12, 9, + 248, 8, 0, 0, 36, 0, + 0, 0, 8, 9, 0, 0, + 39, 0, 0, 0, 24, 9, 0, 0, 41, 0, 0, 0, - 28, 9, 0, 0, 42, 0, - 0, 0, 44, 9, 0, 0, - 42, 0, 0, 0, 60, 9, + 40, 9, 0, 0, 42, 0, + 0, 0, 56, 9, 0, 0, + 42, 0, 0, 0, 72, 9, 0, 0, 42, 0, 0, 0, - 72, 9, 0, 0, 42, 0, - 0, 0, 84, 9, 0, 0, - 42, 0, 0, 0, 96, 9, + 84, 9, 0, 0, 42, 0, + 0, 0, 96, 9, 0, 0, + 42, 0, 0, 0, 108, 9, 0, 0, 42, 0, 0, 0, - 112, 9, 0, 0, 47, 0, - 0, 0, 124, 9, 0, 0, - 42, 0, 0, 0, 140, 9, + 124, 9, 0, 0, 47, 0, + 0, 0, 136, 9, 0, 0, + 42, 0, 0, 0, 152, 9, 0, 0, 42, 0, 0, 0, - 152, 9, 0, 0, 47, 0, - 0, 0, 164, 9, 0, 0, - 47, 0, 0, 0, 184, 9, + 164, 9, 0, 0, 47, 0, + 0, 0, 176, 9, 0, 0, + 47, 0, 0, 0, 196, 9, 0, 0, 47, 0, 0, 0, - 204, 9, 0, 0, 63, 0, - 0, 0, 220, 9, 0, 0, - 14, 0, 1, 0, 236, 9, + 216, 9, 0, 0, 63, 0, + 0, 0, 232, 9, 0, 0, + 14, 0, 1, 0, 248, 9, 0, 0, 14, 0, 1, 0, - 252, 9, 0, 0, 14, 0, - 1, 0, 12, 10, 0, 0, - 46, 0, 0, 0, 28, 10, + 8, 10, 0, 0, 14, 0, + 1, 0, 24, 10, 0, 0, + 46, 0, 0, 0, 40, 10, 0, 0, 46, 0, 0, 0, - 44, 10, 0, 0, 46, 0, - 0, 0, 64, 10, 0, 0, - 46, 0, 0, 0, 84, 10, + 56, 10, 0, 0, 46, 0, + 0, 0, 76, 10, 0, 0, + 46, 0, 0, 0, 96, 10, 0, 0, 46, 0, 0, 0, - 96, 10, 0, 0, 173, 0, - 2, 0, 116, 10, 0, 0, - 173, 0, 2, 0, 132, 10, + 108, 10, 0, 0, 173, 0, + 2, 0, 128, 10, 0, 0, + 173, 0, 2, 0, 144, 10, 0, 0, 63, 0, 0, 0, - 148, 10, 0, 0, 63, 0, - 0, 0, 164, 10, 0, 0, - 63, 0, 0, 0, 180, 10, + 160, 10, 0, 0, 63, 0, + 0, 0, 176, 10, 0, 0, + 63, 0, 0, 0, 192, 10, 0, 0, 166, 0, 2, 0, - 196, 10, 0, 0, 166, 0, - 2, 0, 216, 10, 0, 0, + 208, 10, 0, 0, 166, 0, + 2, 0, 228, 10, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -548,7 +548,9 @@ const BYTE BasicEffect_VSBasicVertexLightingVc[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 25, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main.inc index 23ec2d87..3e489f37 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main.inc @@ -54,7 +54,7 @@ dcl_texcoord2 v2 // vertex<7,8,9,10> dcl_texcoord3 v3 // vertex<11,12> -#line 129 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 129 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" dp4 oPos.z, v0, c7 // ::main<2> mad r0.xyz, v3.xyxw, c12.xxyw, c12.yyxw dp3 oT1.x, r0, c9.xyww // ::main<8> @@ -132,17 +132,17 @@ ret const BYTE DGSLEffect_main[] = { - 68, 88, 66, 67, 182, 249, - 107, 54, 68, 156, 189, 16, - 219, 123, 26, 176, 4, 68, - 179, 66, 1, 0, 0, 0, - 124, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 1, 240, + 120, 128, 204, 184, 59, 192, + 91, 170, 100, 150, 249, 210, + 55, 71, 1, 0, 0, 0, + 136, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 12, 6, 0, 0, 252, 8, - 0, 0, 144, 9, 0, 0, - 65, 111, 110, 57, 212, 5, - 0, 0, 212, 5, 0, 0, - 0, 2, 254, 255, 112, 5, + 24, 6, 0, 0, 8, 9, + 0, 0, 156, 9, 0, 0, + 65, 111, 110, 57, 224, 5, + 0, 0, 224, 5, 0, 0, + 0, 2, 254, 255, 124, 5, 0, 0, 100, 0, 0, 0, 5, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, @@ -159,14 +159,14 @@ const BYTE DGSLEffect_main[] = 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 250, 0, 68, 66, 85, 71, + 253, 0, 68, 66, 85, 71, 40, 0, 0, 0, 188, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 25, 0, 0, 0, 120, 0, 0, 0, 4, 0, 0, 0, 108, 3, 0, 0, - 64, 1, 0, 0, 67, 58, + 64, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -180,39 +180,39 @@ const BYTE DGSLEffect_main[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 240, 3, + 0, 0, 255, 255, 252, 3, 0, 0, 0, 0, 255, 255, - 8, 4, 0, 0, 0, 0, - 255, 255, 20, 4, 0, 0, - 0, 0, 255, 255, 32, 4, + 20, 4, 0, 0, 0, 0, + 255, 255, 32, 4, 0, 0, + 0, 0, 255, 255, 44, 4, 0, 0, 0, 0, 255, 255, - 44, 4, 0, 0, 129, 0, - 0, 0, 56, 4, 0, 0, - 131, 0, 0, 0, 72, 4, + 56, 4, 0, 0, 129, 0, + 0, 0, 68, 4, 0, 0, + 131, 0, 0, 0, 84, 4, 0, 0, 131, 0, 0, 0, - 92, 4, 0, 0, 131, 0, - 0, 0, 108, 4, 0, 0, - 132, 0, 0, 0, 124, 4, + 104, 4, 0, 0, 131, 0, + 0, 0, 120, 4, 0, 0, + 132, 0, 0, 0, 136, 4, 0, 0, 132, 0, 0, 0, - 140, 4, 0, 0, 132, 0, - 0, 0, 156, 4, 0, 0, - 126, 0, 0, 0, 172, 4, + 152, 4, 0, 0, 132, 0, + 0, 0, 168, 4, 0, 0, + 126, 0, 0, 0, 184, 4, 0, 0, 126, 0, 0, 0, - 188, 4, 0, 0, 126, 0, - 0, 0, 204, 4, 0, 0, - 134, 0, 0, 0, 220, 4, + 200, 4, 0, 0, 126, 0, + 0, 0, 216, 4, 0, 0, + 134, 0, 0, 0, 232, 4, 0, 0, 126, 0, 0, 0, - 236, 4, 0, 0, 129, 0, - 0, 0, 248, 4, 0, 0, - 129, 0, 0, 0, 8, 5, + 248, 4, 0, 0, 129, 0, + 0, 0, 4, 5, 0, 0, + 129, 0, 0, 0, 20, 5, 0, 0, 129, 0, 0, 0, - 24, 5, 0, 0, 122, 0, - 0, 0, 40, 5, 0, 0, - 122, 0, 0, 0, 60, 5, + 36, 5, 0, 0, 122, 0, + 0, 0, 52, 5, 0, 0, + 122, 0, 0, 0, 72, 5, 0, 0, 130, 0, 0, 0, - 72, 5, 0, 0, 135, 0, - 0, 0, 84, 5, 0, 0, - 136, 0, 0, 0, 96, 5, + 84, 5, 0, 0, 135, 0, + 0, 0, 96, 5, 0, 0, + 136, 0, 0, 0, 108, 5, 0, 0, 109, 97, 105, 110, 0, 112, 111, 115, 0, 171, 171, 171, 1, 0, 3, 0, @@ -325,7 +325,9 @@ const BYTE DGSLEffect_main[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 12, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1Bones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1Bones.inc index 9ba5a332..70143438 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1Bones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1Bones.inc @@ -59,7 +59,7 @@ dcl_texcoord4 v4 // vertex<13,14,15,16> dcl_texcoord5 v5 // vertex<17,18,19,20> -#line 97 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 97 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0.x, v4.x, c228.x mova a0.x, r0.x mul r0, v5.x, c0[a0.x] // ::skinning<0,3,6,9> @@ -181,17 +181,17 @@ ret const BYTE DGSLEffect_main1Bones[] = { - 68, 88, 66, 67, 33, 52, - 28, 59, 16, 79, 211, 114, - 159, 203, 173, 27, 152, 183, - 209, 184, 1, 0, 0, 0, - 100, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 10, 250, + 228, 168, 240, 222, 35, 154, + 123, 90, 154, 177, 210, 27, + 24, 133, 1, 0, 0, 0, + 112, 15, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 220, 8, 0, 0, 152, 13, - 0, 0, 120, 14, 0, 0, - 65, 111, 110, 57, 164, 8, - 0, 0, 164, 8, 0, 0, - 0, 2, 254, 255, 52, 8, + 232, 8, 0, 0, 164, 13, + 0, 0, 132, 14, 0, 0, + 65, 111, 110, 57, 176, 8, + 0, 0, 176, 8, 0, 0, + 0, 2, 254, 255, 64, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -210,14 +210,14 @@ const BYTE DGSLEffect_main1Bones[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 104, 1, 68, 66, 85, 71, + 107, 1, 68, 66, 85, 71, 40, 0, 0, 0, 116, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 42, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 252, 4, 0, 0, - 200, 1, 0, 0, 67, 58, + 200, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -231,62 +231,62 @@ const BYTE DGSLEffect_main1Bones[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 168, 5, + 0, 0, 255, 255, 180, 5, 0, 0, 0, 0, 255, 255, - 192, 5, 0, 0, 0, 0, - 255, 255, 204, 5, 0, 0, - 0, 0, 255, 255, 216, 5, + 204, 5, 0, 0, 0, 0, + 255, 255, 216, 5, 0, 0, + 0, 0, 255, 255, 228, 5, 0, 0, 0, 0, 255, 255, - 228, 5, 0, 0, 0, 0, - 255, 255, 240, 5, 0, 0, - 0, 0, 255, 255, 252, 5, + 240, 5, 0, 0, 0, 0, + 255, 255, 252, 5, 0, 0, + 0, 0, 255, 255, 8, 6, 0, 0, 97, 0, 0, 0, - 8, 6, 0, 0, 97, 0, - 0, 0, 24, 6, 0, 0, - 97, 0, 0, 0, 36, 6, + 20, 6, 0, 0, 97, 0, + 0, 0, 36, 6, 0, 0, + 97, 0, 0, 0, 48, 6, 0, 0, 102, 0, 0, 0, - 56, 6, 0, 0, 97, 0, - 0, 0, 72, 6, 0, 0, - 97, 0, 0, 0, 92, 6, + 68, 6, 0, 0, 97, 0, + 0, 0, 84, 6, 0, 0, + 97, 0, 0, 0, 104, 6, 0, 0, 102, 0, 0, 0, - 112, 6, 0, 0, 102, 0, - 0, 0, 128, 6, 0, 0, - 100, 0, 0, 0, 144, 6, + 124, 6, 0, 0, 102, 0, + 0, 0, 140, 6, 0, 0, + 100, 0, 0, 0, 156, 6, 0, 0, 101, 0, 0, 0, - 160, 6, 0, 0, 100, 0, - 0, 0, 176, 6, 0, 0, - 101, 0, 0, 0, 192, 6, + 172, 6, 0, 0, 100, 0, + 0, 0, 188, 6, 0, 0, + 101, 0, 0, 0, 204, 6, 0, 0, 100, 0, 0, 0, - 208, 6, 0, 0, 101, 0, - 0, 0, 224, 6, 0, 0, - 170, 0, 0, 0, 240, 6, + 220, 6, 0, 0, 101, 0, + 0, 0, 236, 6, 0, 0, + 170, 0, 0, 0, 252, 6, 0, 0, 173, 0, 0, 0, - 252, 6, 0, 0, 175, 0, - 0, 0, 12, 7, 0, 0, - 175, 0, 0, 0, 32, 7, + 8, 7, 0, 0, 175, 0, + 0, 0, 24, 7, 0, 0, + 175, 0, 0, 0, 44, 7, 0, 0, 175, 0, 0, 0, - 48, 7, 0, 0, 176, 0, - 0, 0, 64, 7, 0, 0, - 176, 0, 0, 0, 80, 7, + 60, 7, 0, 0, 176, 0, + 0, 0, 76, 7, 0, 0, + 176, 0, 0, 0, 92, 7, 0, 0, 176, 0, 0, 0, - 96, 7, 0, 0, 101, 0, - 0, 0, 112, 7, 0, 0, - 170, 0, 0, 0, 124, 7, + 108, 7, 0, 0, 101, 0, + 0, 0, 124, 7, 0, 0, + 170, 0, 0, 0, 136, 7, 0, 0, 170, 0, 0, 0, - 140, 7, 0, 0, 170, 0, - 0, 0, 156, 7, 0, 0, - 178, 0, 0, 0, 172, 7, + 152, 7, 0, 0, 170, 0, + 0, 0, 168, 7, 0, 0, + 178, 0, 0, 0, 184, 7, 0, 0, 170, 0, 0, 0, - 188, 7, 0, 0, 173, 0, - 0, 0, 200, 7, 0, 0, - 173, 0, 0, 0, 216, 7, + 200, 7, 0, 0, 173, 0, + 0, 0, 212, 7, 0, 0, + 173, 0, 0, 0, 228, 7, 0, 0, 173, 0, 0, 0, - 232, 7, 0, 0, 164, 0, - 0, 0, 248, 7, 0, 0, - 164, 0, 0, 0, 12, 8, + 244, 7, 0, 0, 164, 0, + 0, 0, 4, 8, 0, 0, + 164, 0, 0, 0, 24, 8, 0, 0, 174, 0, 0, 0, - 24, 8, 0, 0, 102, 0, - 0, 0, 36, 8, 0, 0, + 36, 8, 0, 0, 102, 0, + 0, 0, 48, 8, 0, 0, 109, 97, 105, 110, 49, 66, 111, 110, 101, 115, 0, 112, 111, 115, 0, 171, 1, 0, @@ -450,7 +450,9 @@ const BYTE DGSLEffect_main1Bones[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1BonesVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1BonesVc.inc index d2a4e2b0..f61ee961 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1BonesVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main1BonesVc.inc @@ -61,7 +61,7 @@ dcl_texcoord5 v5 // vertex<17,18,19,20> dcl_texcoord6 v6 // vertex<21,22,23,24> -#line 112 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 112 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0.x, v5.x, c228.x mova a0.x, r0.x mul r0, v6.x, c0[a0.x] // ::skinning<0,3,6,9> @@ -182,17 +182,17 @@ ret const BYTE DGSLEffect_main1BonesVc[] = { - 68, 88, 66, 67, 128, 178, - 178, 97, 125, 167, 70, 197, - 27, 237, 13, 172, 173, 144, - 242, 53, 1, 0, 0, 0, - 204, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 141, 159, + 240, 217, 243, 98, 5, 22, + 173, 30, 24, 5, 224, 54, + 7, 203, 1, 0, 0, 0, + 216, 15, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 20, 9, 0, 0, 228, 13, - 0, 0, 224, 14, 0, 0, - 65, 111, 110, 57, 220, 8, - 0, 0, 220, 8, 0, 0, - 0, 2, 254, 255, 108, 8, + 32, 9, 0, 0, 240, 13, + 0, 0, 236, 14, 0, 0, + 65, 111, 110, 57, 232, 8, + 0, 0, 232, 8, 0, 0, + 0, 2, 254, 255, 120, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -211,14 +211,14 @@ const BYTE DGSLEffect_main1BonesVc[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 114, 1, 68, 66, 85, 71, + 117, 1, 68, 66, 85, 71, 40, 0, 0, 0, 156, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 43, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 36, 5, 0, 0, - 208, 1, 0, 0, 67, 58, + 208, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -232,63 +232,63 @@ const BYTE DGSLEffect_main1BonesVc[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 208, 5, + 0, 0, 255, 255, 220, 5, 0, 0, 0, 0, 255, 255, - 232, 5, 0, 0, 0, 0, - 255, 255, 244, 5, 0, 0, - 0, 0, 255, 255, 0, 6, + 244, 5, 0, 0, 0, 0, + 255, 255, 0, 6, 0, 0, + 0, 0, 255, 255, 12, 6, 0, 0, 0, 0, 255, 255, - 12, 6, 0, 0, 0, 0, - 255, 255, 24, 6, 0, 0, - 0, 0, 255, 255, 36, 6, + 24, 6, 0, 0, 0, 0, + 255, 255, 36, 6, 0, 0, + 0, 0, 255, 255, 48, 6, 0, 0, 0, 0, 255, 255, - 48, 6, 0, 0, 112, 0, - 0, 0, 60, 6, 0, 0, - 112, 0, 0, 0, 76, 6, + 60, 6, 0, 0, 112, 0, + 0, 0, 72, 6, 0, 0, + 112, 0, 0, 0, 88, 6, 0, 0, 112, 0, 0, 0, - 88, 6, 0, 0, 117, 0, - 0, 0, 108, 6, 0, 0, - 112, 0, 0, 0, 124, 6, + 100, 6, 0, 0, 117, 0, + 0, 0, 120, 6, 0, 0, + 112, 0, 0, 0, 136, 6, 0, 0, 112, 0, 0, 0, - 144, 6, 0, 0, 117, 0, - 0, 0, 164, 6, 0, 0, - 117, 0, 0, 0, 180, 6, + 156, 6, 0, 0, 117, 0, + 0, 0, 176, 6, 0, 0, + 117, 0, 0, 0, 192, 6, 0, 0, 115, 0, 0, 0, - 196, 6, 0, 0, 116, 0, - 0, 0, 212, 6, 0, 0, - 115, 0, 0, 0, 228, 6, + 208, 6, 0, 0, 116, 0, + 0, 0, 224, 6, 0, 0, + 115, 0, 0, 0, 240, 6, 0, 0, 116, 0, 0, 0, - 244, 6, 0, 0, 115, 0, - 0, 0, 4, 7, 0, 0, - 116, 0, 0, 0, 20, 7, + 0, 7, 0, 0, 115, 0, + 0, 0, 16, 7, 0, 0, + 116, 0, 0, 0, 32, 7, 0, 0, 237, 0, 0, 0, - 36, 7, 0, 0, 240, 0, - 0, 0, 48, 7, 0, 0, - 241, 0, 0, 0, 64, 7, + 48, 7, 0, 0, 240, 0, + 0, 0, 60, 7, 0, 0, + 241, 0, 0, 0, 76, 7, 0, 0, 242, 0, 0, 0, - 80, 7, 0, 0, 242, 0, - 0, 0, 100, 7, 0, 0, - 242, 0, 0, 0, 116, 7, + 92, 7, 0, 0, 242, 0, + 0, 0, 112, 7, 0, 0, + 242, 0, 0, 0, 128, 7, 0, 0, 243, 0, 0, 0, - 132, 7, 0, 0, 243, 0, - 0, 0, 148, 7, 0, 0, - 243, 0, 0, 0, 164, 7, + 144, 7, 0, 0, 243, 0, + 0, 0, 160, 7, 0, 0, + 243, 0, 0, 0, 176, 7, 0, 0, 116, 0, 0, 0, - 180, 7, 0, 0, 237, 0, - 0, 0, 192, 7, 0, 0, - 237, 0, 0, 0, 208, 7, + 192, 7, 0, 0, 237, 0, + 0, 0, 204, 7, 0, 0, + 237, 0, 0, 0, 220, 7, 0, 0, 237, 0, 0, 0, - 224, 7, 0, 0, 245, 0, - 0, 0, 240, 7, 0, 0, - 237, 0, 0, 0, 0, 8, + 236, 7, 0, 0, 245, 0, + 0, 0, 252, 7, 0, 0, + 237, 0, 0, 0, 12, 8, 0, 0, 240, 0, 0, 0, - 12, 8, 0, 0, 240, 0, - 0, 0, 28, 8, 0, 0, - 240, 0, 0, 0, 44, 8, + 24, 8, 0, 0, 240, 0, + 0, 0, 40, 8, 0, 0, + 240, 0, 0, 0, 56, 8, 0, 0, 231, 0, 0, 0, - 60, 8, 0, 0, 231, 0, - 0, 0, 80, 8, 0, 0, - 117, 0, 0, 0, 92, 8, + 72, 8, 0, 0, 231, 0, + 0, 0, 92, 8, 0, 0, + 117, 0, 0, 0, 104, 8, 0, 0, 109, 97, 105, 110, 49, 66, 111, 110, 101, 115, 86, 99, 0, 112, 111, 115, @@ -457,7 +457,9 @@ const BYTE DGSLEffect_main1BonesVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2Bones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2Bones.inc index 5f4e67ef..6b627953 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2Bones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2Bones.inc @@ -59,7 +59,7 @@ dcl_texcoord4 v4 // vertex<13,14,15,16> dcl_texcoord5 v5 // vertex<17,18,19,20> -#line 97 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 97 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0.xy, v4, c228.x mova a0.xy, r0.yxzw mul r0, v5.y, c0[a0.x] @@ -187,17 +187,17 @@ ret const BYTE DGSLEffect_main2Bones[] = { - 68, 88, 66, 67, 139, 240, - 154, 192, 91, 144, 240, 213, - 181, 251, 99, 29, 57, 102, - 52, 224, 1, 0, 0, 0, - 92, 16, 0, 0, 4, 0, + 68, 88, 66, 67, 72, 37, + 145, 182, 220, 28, 92, 2, + 19, 74, 174, 145, 89, 96, + 115, 87, 1, 0, 0, 0, + 104, 16, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 60, 9, 0, 0, 144, 14, - 0, 0, 112, 15, 0, 0, - 65, 111, 110, 57, 4, 9, - 0, 0, 4, 9, 0, 0, - 0, 2, 254, 255, 148, 8, + 72, 9, 0, 0, 156, 14, + 0, 0, 124, 15, 0, 0, + 65, 111, 110, 57, 16, 9, + 0, 0, 16, 9, 0, 0, + 0, 2, 254, 255, 160, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -216,14 +216,14 @@ const BYTE DGSLEffect_main2Bones[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 110, 1, 68, 66, 85, 71, + 113, 1, 68, 66, 85, 71, 40, 0, 0, 0, 140, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 45, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 20, 5, 0, 0, - 224, 1, 0, 0, 67, 58, + 224, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -237,66 +237,66 @@ const BYTE DGSLEffect_main2Bones[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 192, 5, + 0, 0, 255, 255, 204, 5, 0, 0, 0, 0, 255, 255, - 216, 5, 0, 0, 0, 0, - 255, 255, 228, 5, 0, 0, - 0, 0, 255, 255, 240, 5, + 228, 5, 0, 0, 0, 0, + 255, 255, 240, 5, 0, 0, + 0, 0, 255, 255, 252, 5, 0, 0, 0, 0, 255, 255, - 252, 5, 0, 0, 0, 0, - 255, 255, 8, 6, 0, 0, - 0, 0, 255, 255, 20, 6, + 8, 6, 0, 0, 0, 0, + 255, 255, 20, 6, 0, 0, + 0, 0, 255, 255, 32, 6, 0, 0, 97, 0, 0, 0, - 32, 6, 0, 0, 97, 0, - 0, 0, 48, 6, 0, 0, - 97, 0, 0, 0, 60, 6, + 44, 6, 0, 0, 97, 0, + 0, 0, 60, 6, 0, 0, + 97, 0, 0, 0, 72, 6, 0, 0, 97, 0, 0, 0, - 80, 6, 0, 0, 102, 0, - 0, 0, 104, 6, 0, 0, - 97, 0, 0, 0, 120, 6, + 92, 6, 0, 0, 102, 0, + 0, 0, 116, 6, 0, 0, + 97, 0, 0, 0, 132, 6, 0, 0, 97, 0, 0, 0, - 140, 6, 0, 0, 97, 0, - 0, 0, 160, 6, 0, 0, - 97, 0, 0, 0, 184, 6, + 152, 6, 0, 0, 97, 0, + 0, 0, 172, 6, 0, 0, + 97, 0, 0, 0, 196, 6, 0, 0, 102, 0, 0, 0, - 208, 6, 0, 0, 102, 0, - 0, 0, 224, 6, 0, 0, - 100, 0, 0, 0, 240, 6, + 220, 6, 0, 0, 102, 0, + 0, 0, 236, 6, 0, 0, + 100, 0, 0, 0, 252, 6, 0, 0, 101, 0, 0, 0, - 0, 7, 0, 0, 100, 0, - 0, 0, 16, 7, 0, 0, - 101, 0, 0, 0, 32, 7, + 12, 7, 0, 0, 100, 0, + 0, 0, 28, 7, 0, 0, + 101, 0, 0, 0, 44, 7, 0, 0, 100, 0, 0, 0, - 48, 7, 0, 0, 101, 0, - 0, 0, 64, 7, 0, 0, - 192, 0, 0, 0, 80, 7, + 60, 7, 0, 0, 101, 0, + 0, 0, 76, 7, 0, 0, + 192, 0, 0, 0, 92, 7, 0, 0, 195, 0, 0, 0, - 92, 7, 0, 0, 197, 0, - 0, 0, 108, 7, 0, 0, - 197, 0, 0, 0, 128, 7, + 104, 7, 0, 0, 197, 0, + 0, 0, 120, 7, 0, 0, + 197, 0, 0, 0, 140, 7, 0, 0, 197, 0, 0, 0, - 144, 7, 0, 0, 198, 0, - 0, 0, 160, 7, 0, 0, - 198, 0, 0, 0, 176, 7, + 156, 7, 0, 0, 198, 0, + 0, 0, 172, 7, 0, 0, + 198, 0, 0, 0, 188, 7, 0, 0, 198, 0, 0, 0, - 192, 7, 0, 0, 101, 0, - 0, 0, 208, 7, 0, 0, - 192, 0, 0, 0, 220, 7, + 204, 7, 0, 0, 101, 0, + 0, 0, 220, 7, 0, 0, + 192, 0, 0, 0, 232, 7, 0, 0, 192, 0, 0, 0, - 236, 7, 0, 0, 192, 0, - 0, 0, 252, 7, 0, 0, - 200, 0, 0, 0, 12, 8, + 248, 7, 0, 0, 192, 0, + 0, 0, 8, 8, 0, 0, + 200, 0, 0, 0, 24, 8, 0, 0, 192, 0, 0, 0, - 28, 8, 0, 0, 195, 0, - 0, 0, 40, 8, 0, 0, - 195, 0, 0, 0, 56, 8, + 40, 8, 0, 0, 195, 0, + 0, 0, 52, 8, 0, 0, + 195, 0, 0, 0, 68, 8, 0, 0, 195, 0, 0, 0, - 72, 8, 0, 0, 186, 0, - 0, 0, 88, 8, 0, 0, - 186, 0, 0, 0, 108, 8, + 84, 8, 0, 0, 186, 0, + 0, 0, 100, 8, 0, 0, + 186, 0, 0, 0, 120, 8, 0, 0, 196, 0, 0, 0, - 120, 8, 0, 0, 102, 0, - 0, 0, 132, 8, 0, 0, + 132, 8, 0, 0, 102, 0, + 0, 0, 144, 8, 0, 0, 109, 97, 105, 110, 50, 66, 111, 110, 101, 115, 0, 112, 111, 115, 0, 171, 1, 0, @@ -460,7 +460,9 @@ const BYTE DGSLEffect_main2Bones[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2BonesVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2BonesVc.inc index 48e32b00..f32408f2 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2BonesVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main2BonesVc.inc @@ -61,7 +61,7 @@ dcl_texcoord5 v5 // vertex<17,18,19,20> dcl_texcoord6 v6 // vertex<21,22,23,24> -#line 112 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 112 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0.xy, v5, c228.x mova a0.xy, r0.yxzw mul r0, v6.y, c0[a0.x] @@ -188,17 +188,17 @@ ret const BYTE DGSLEffect_main2BonesVc[] = { - 68, 88, 66, 67, 123, 121, - 55, 167, 3, 144, 97, 7, - 118, 119, 195, 195, 188, 134, - 242, 194, 1, 0, 0, 0, - 196, 16, 0, 0, 4, 0, + 68, 88, 66, 67, 104, 53, + 27, 45, 154, 36, 224, 246, + 235, 73, 156, 185, 196, 186, + 78, 74, 1, 0, 0, 0, + 208, 16, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 116, 9, 0, 0, 220, 14, - 0, 0, 216, 15, 0, 0, - 65, 111, 110, 57, 60, 9, - 0, 0, 60, 9, 0, 0, - 0, 2, 254, 255, 204, 8, + 128, 9, 0, 0, 232, 14, + 0, 0, 228, 15, 0, 0, + 65, 111, 110, 57, 72, 9, + 0, 0, 72, 9, 0, 0, + 0, 2, 254, 255, 216, 8, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -217,14 +217,14 @@ const BYTE DGSLEffect_main2BonesVc[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 120, 1, 68, 66, 85, 71, + 123, 1, 68, 66, 85, 71, 40, 0, 0, 0, 180, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 46, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 60, 5, 0, 0, - 232, 1, 0, 0, 67, 58, + 232, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -238,67 +238,67 @@ const BYTE DGSLEffect_main2BonesVc[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 232, 5, + 0, 0, 255, 255, 244, 5, 0, 0, 0, 0, 255, 255, - 0, 6, 0, 0, 0, 0, - 255, 255, 12, 6, 0, 0, - 0, 0, 255, 255, 24, 6, + 12, 6, 0, 0, 0, 0, + 255, 255, 24, 6, 0, 0, + 0, 0, 255, 255, 36, 6, 0, 0, 0, 0, 255, 255, - 36, 6, 0, 0, 0, 0, - 255, 255, 48, 6, 0, 0, - 0, 0, 255, 255, 60, 6, + 48, 6, 0, 0, 0, 0, + 255, 255, 60, 6, 0, 0, + 0, 0, 255, 255, 72, 6, 0, 0, 0, 0, 255, 255, - 72, 6, 0, 0, 112, 0, - 0, 0, 84, 6, 0, 0, - 112, 0, 0, 0, 100, 6, + 84, 6, 0, 0, 112, 0, + 0, 0, 96, 6, 0, 0, + 112, 0, 0, 0, 112, 6, 0, 0, 112, 0, 0, 0, - 112, 6, 0, 0, 112, 0, - 0, 0, 132, 6, 0, 0, - 117, 0, 0, 0, 156, 6, + 124, 6, 0, 0, 112, 0, + 0, 0, 144, 6, 0, 0, + 117, 0, 0, 0, 168, 6, 0, 0, 112, 0, 0, 0, - 172, 6, 0, 0, 112, 0, - 0, 0, 192, 6, 0, 0, - 112, 0, 0, 0, 212, 6, + 184, 6, 0, 0, 112, 0, + 0, 0, 204, 6, 0, 0, + 112, 0, 0, 0, 224, 6, 0, 0, 112, 0, 0, 0, - 236, 6, 0, 0, 117, 0, - 0, 0, 4, 7, 0, 0, - 117, 0, 0, 0, 20, 7, + 248, 6, 0, 0, 117, 0, + 0, 0, 16, 7, 0, 0, + 117, 0, 0, 0, 32, 7, 0, 0, 115, 0, 0, 0, - 36, 7, 0, 0, 116, 0, - 0, 0, 52, 7, 0, 0, - 115, 0, 0, 0, 68, 7, + 48, 7, 0, 0, 116, 0, + 0, 0, 64, 7, 0, 0, + 115, 0, 0, 0, 80, 7, 0, 0, 116, 0, 0, 0, - 84, 7, 0, 0, 115, 0, - 0, 0, 100, 7, 0, 0, - 116, 0, 0, 0, 116, 7, + 96, 7, 0, 0, 115, 0, + 0, 0, 112, 7, 0, 0, + 116, 0, 0, 0, 128, 7, 0, 0, 3, 1, 0, 0, - 132, 7, 0, 0, 6, 1, - 0, 0, 144, 7, 0, 0, - 7, 1, 0, 0, 160, 7, + 144, 7, 0, 0, 6, 1, + 0, 0, 156, 7, 0, 0, + 7, 1, 0, 0, 172, 7, 0, 0, 8, 1, 0, 0, - 176, 7, 0, 0, 8, 1, - 0, 0, 196, 7, 0, 0, - 8, 1, 0, 0, 212, 7, + 188, 7, 0, 0, 8, 1, + 0, 0, 208, 7, 0, 0, + 8, 1, 0, 0, 224, 7, 0, 0, 9, 1, 0, 0, - 228, 7, 0, 0, 9, 1, - 0, 0, 244, 7, 0, 0, - 9, 1, 0, 0, 4, 8, + 240, 7, 0, 0, 9, 1, + 0, 0, 0, 8, 0, 0, + 9, 1, 0, 0, 16, 8, 0, 0, 116, 0, 0, 0, - 20, 8, 0, 0, 3, 1, - 0, 0, 32, 8, 0, 0, - 3, 1, 0, 0, 48, 8, + 32, 8, 0, 0, 3, 1, + 0, 0, 44, 8, 0, 0, + 3, 1, 0, 0, 60, 8, 0, 0, 3, 1, 0, 0, - 64, 8, 0, 0, 11, 1, - 0, 0, 80, 8, 0, 0, - 3, 1, 0, 0, 96, 8, + 76, 8, 0, 0, 11, 1, + 0, 0, 92, 8, 0, 0, + 3, 1, 0, 0, 108, 8, 0, 0, 6, 1, 0, 0, - 108, 8, 0, 0, 6, 1, - 0, 0, 124, 8, 0, 0, - 6, 1, 0, 0, 140, 8, + 120, 8, 0, 0, 6, 1, + 0, 0, 136, 8, 0, 0, + 6, 1, 0, 0, 152, 8, 0, 0, 253, 0, 0, 0, - 156, 8, 0, 0, 253, 0, - 0, 0, 176, 8, 0, 0, - 117, 0, 0, 0, 188, 8, + 168, 8, 0, 0, 253, 0, + 0, 0, 188, 8, 0, 0, + 117, 0, 0, 0, 200, 8, 0, 0, 109, 97, 105, 110, 50, 66, 111, 110, 101, 115, 86, 99, 0, 112, 111, 115, @@ -467,7 +467,9 @@ const BYTE DGSLEffect_main2BonesVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4Bones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4Bones.inc index eeb8a888..f3ddf494 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4Bones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4Bones.inc @@ -59,7 +59,7 @@ dcl_texcoord4 v4 // vertex<13,14,15,16> dcl_texcoord5 v5 // vertex<17,18,19,20> -#line 97 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 97 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0, v4, c228.x mova a0, r0.yxzw mul r1, v5.y, c0[a0.x] @@ -199,17 +199,17 @@ ret const BYTE DGSLEffect_main4Bones[] = { - 68, 88, 66, 67, 45, 137, - 208, 23, 220, 71, 47, 74, - 63, 1, 119, 83, 15, 78, - 96, 247, 1, 0, 0, 0, - 124, 18, 0, 0, 4, 0, + 68, 88, 66, 67, 234, 113, + 27, 144, 43, 126, 67, 181, + 199, 109, 119, 34, 125, 74, + 133, 160, 1, 0, 0, 0, + 136, 18, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 68, 10, 0, 0, 176, 16, - 0, 0, 144, 17, 0, 0, - 65, 111, 110, 57, 12, 10, - 0, 0, 12, 10, 0, 0, - 0, 2, 254, 255, 156, 9, + 80, 10, 0, 0, 188, 16, + 0, 0, 156, 17, 0, 0, + 65, 111, 110, 57, 24, 10, + 0, 0, 24, 10, 0, 0, + 0, 2, 254, 255, 168, 9, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -228,14 +228,14 @@ const BYTE DGSLEffect_main4Bones[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 140, 1, 68, 66, 85, 71, + 143, 1, 68, 66, 85, 71, 40, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 51, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 140, 5, 0, 0, - 16, 2, 0, 0, 67, 58, + 16, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -249,74 +249,74 @@ const BYTE DGSLEffect_main4Bones[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 56, 6, + 0, 0, 255, 255, 68, 6, 0, 0, 0, 0, 255, 255, - 80, 6, 0, 0, 0, 0, - 255, 255, 92, 6, 0, 0, - 0, 0, 255, 255, 104, 6, + 92, 6, 0, 0, 0, 0, + 255, 255, 104, 6, 0, 0, + 0, 0, 255, 255, 116, 6, 0, 0, 0, 0, 255, 255, - 116, 6, 0, 0, 0, 0, - 255, 255, 128, 6, 0, 0, - 0, 0, 255, 255, 140, 6, + 128, 6, 0, 0, 0, 0, + 255, 255, 140, 6, 0, 0, + 0, 0, 255, 255, 152, 6, 0, 0, 97, 0, 0, 0, - 152, 6, 0, 0, 97, 0, - 0, 0, 168, 6, 0, 0, - 97, 0, 0, 0, 180, 6, + 164, 6, 0, 0, 97, 0, + 0, 0, 180, 6, 0, 0, + 97, 0, 0, 0, 192, 6, 0, 0, 97, 0, 0, 0, - 200, 6, 0, 0, 97, 0, - 0, 0, 224, 6, 0, 0, - 97, 0, 0, 0, 248, 6, + 212, 6, 0, 0, 97, 0, + 0, 0, 236, 6, 0, 0, + 97, 0, 0, 0, 4, 7, 0, 0, 102, 0, 0, 0, - 16, 7, 0, 0, 97, 0, - 0, 0, 32, 7, 0, 0, - 97, 0, 0, 0, 52, 7, + 28, 7, 0, 0, 97, 0, + 0, 0, 44, 7, 0, 0, + 97, 0, 0, 0, 64, 7, 0, 0, 97, 0, 0, 0, - 72, 7, 0, 0, 97, 0, - 0, 0, 96, 7, 0, 0, - 97, 0, 0, 0, 120, 7, + 84, 7, 0, 0, 97, 0, + 0, 0, 108, 7, 0, 0, + 97, 0, 0, 0, 132, 7, 0, 0, 97, 0, 0, 0, - 144, 7, 0, 0, 97, 0, - 0, 0, 168, 7, 0, 0, - 97, 0, 0, 0, 192, 7, + 156, 7, 0, 0, 97, 0, + 0, 0, 180, 7, 0, 0, + 97, 0, 0, 0, 204, 7, 0, 0, 102, 0, 0, 0, - 216, 7, 0, 0, 102, 0, - 0, 0, 232, 7, 0, 0, - 100, 0, 0, 0, 248, 7, + 228, 7, 0, 0, 102, 0, + 0, 0, 244, 7, 0, 0, + 100, 0, 0, 0, 4, 8, 0, 0, 101, 0, 0, 0, - 8, 8, 0, 0, 100, 0, - 0, 0, 24, 8, 0, 0, - 101, 0, 0, 0, 40, 8, + 20, 8, 0, 0, 100, 0, + 0, 0, 36, 8, 0, 0, + 101, 0, 0, 0, 52, 8, 0, 0, 100, 0, 0, 0, - 56, 8, 0, 0, 101, 0, - 0, 0, 72, 8, 0, 0, - 214, 0, 0, 0, 88, 8, + 68, 8, 0, 0, 101, 0, + 0, 0, 84, 8, 0, 0, + 214, 0, 0, 0, 100, 8, 0, 0, 217, 0, 0, 0, - 100, 8, 0, 0, 219, 0, - 0, 0, 116, 8, 0, 0, - 219, 0, 0, 0, 136, 8, + 112, 8, 0, 0, 219, 0, + 0, 0, 128, 8, 0, 0, + 219, 0, 0, 0, 148, 8, 0, 0, 219, 0, 0, 0, - 152, 8, 0, 0, 220, 0, - 0, 0, 168, 8, 0, 0, - 220, 0, 0, 0, 184, 8, + 164, 8, 0, 0, 220, 0, + 0, 0, 180, 8, 0, 0, + 220, 0, 0, 0, 196, 8, 0, 0, 220, 0, 0, 0, - 200, 8, 0, 0, 101, 0, - 0, 0, 216, 8, 0, 0, - 214, 0, 0, 0, 228, 8, + 212, 8, 0, 0, 101, 0, + 0, 0, 228, 8, 0, 0, + 214, 0, 0, 0, 240, 8, 0, 0, 214, 0, 0, 0, - 244, 8, 0, 0, 214, 0, - 0, 0, 4, 9, 0, 0, - 222, 0, 0, 0, 20, 9, + 0, 9, 0, 0, 214, 0, + 0, 0, 16, 9, 0, 0, + 222, 0, 0, 0, 32, 9, 0, 0, 214, 0, 0, 0, - 36, 9, 0, 0, 217, 0, - 0, 0, 48, 9, 0, 0, - 217, 0, 0, 0, 64, 9, + 48, 9, 0, 0, 217, 0, + 0, 0, 60, 9, 0, 0, + 217, 0, 0, 0, 76, 9, 0, 0, 217, 0, 0, 0, - 80, 9, 0, 0, 208, 0, - 0, 0, 96, 9, 0, 0, - 208, 0, 0, 0, 116, 9, + 92, 9, 0, 0, 208, 0, + 0, 0, 108, 9, 0, 0, + 208, 0, 0, 0, 128, 9, 0, 0, 218, 0, 0, 0, - 128, 9, 0, 0, 102, 0, - 0, 0, 140, 9, 0, 0, + 140, 9, 0, 0, 102, 0, + 0, 0, 152, 9, 0, 0, 109, 97, 105, 110, 52, 66, 111, 110, 101, 115, 0, 112, 111, 115, 0, 171, 1, 0, @@ -492,7 +492,9 @@ const BYTE DGSLEffect_main4Bones[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4BonesVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4BonesVc.inc index 05350262..74b997f7 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4BonesVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_main4BonesVc.inc @@ -61,7 +61,7 @@ dcl_texcoord5 v5 // vertex<17,18,19,20> dcl_texcoord6 v6 // vertex<21,22,23,24> -#line 112 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 112 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" mul r0, v5, c228.x mova a0, r0.yxzw mul r1, v6.y, c0[a0.x] @@ -200,17 +200,17 @@ ret const BYTE DGSLEffect_main4BonesVc[] = { - 68, 88, 66, 67, 178, 12, - 145, 116, 251, 101, 57, 238, - 157, 61, 44, 74, 40, 241, - 240, 56, 1, 0, 0, 0, - 228, 18, 0, 0, 4, 0, + 68, 88, 66, 67, 13, 121, + 181, 229, 128, 1, 144, 68, + 23, 22, 103, 175, 254, 219, + 139, 119, 1, 0, 0, 0, + 240, 18, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 124, 10, 0, 0, 252, 16, - 0, 0, 248, 17, 0, 0, - 65, 111, 110, 57, 68, 10, - 0, 0, 68, 10, 0, 0, - 0, 2, 254, 255, 212, 9, + 136, 10, 0, 0, 8, 17, + 0, 0, 4, 18, 0, 0, + 65, 111, 110, 57, 80, 10, + 0, 0, 80, 10, 0, 0, + 0, 2, 254, 255, 224, 9, 0, 0, 112, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -229,14 +229,14 @@ const BYTE DGSLEffect_main4BonesVc[] = 1, 0, 227, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 2, 254, 255, 254, 255, - 150, 1, 68, 66, 85, 71, + 153, 1, 68, 66, 85, 71, 40, 0, 0, 0, 44, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 52, 0, 0, 0, 120, 0, 0, 0, 6, 0, 0, 0, 180, 5, 0, 0, - 24, 2, 0, 0, 67, 58, + 24, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -250,75 +250,75 @@ const BYTE DGSLEffect_main4BonesVc[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 96, 6, + 0, 0, 255, 255, 108, 6, 0, 0, 0, 0, 255, 255, - 120, 6, 0, 0, 0, 0, - 255, 255, 132, 6, 0, 0, - 0, 0, 255, 255, 144, 6, + 132, 6, 0, 0, 0, 0, + 255, 255, 144, 6, 0, 0, + 0, 0, 255, 255, 156, 6, 0, 0, 0, 0, 255, 255, - 156, 6, 0, 0, 0, 0, - 255, 255, 168, 6, 0, 0, - 0, 0, 255, 255, 180, 6, + 168, 6, 0, 0, 0, 0, + 255, 255, 180, 6, 0, 0, + 0, 0, 255, 255, 192, 6, 0, 0, 0, 0, 255, 255, - 192, 6, 0, 0, 112, 0, - 0, 0, 204, 6, 0, 0, - 112, 0, 0, 0, 220, 6, + 204, 6, 0, 0, 112, 0, + 0, 0, 216, 6, 0, 0, + 112, 0, 0, 0, 232, 6, 0, 0, 112, 0, 0, 0, - 232, 6, 0, 0, 112, 0, - 0, 0, 252, 6, 0, 0, - 112, 0, 0, 0, 20, 7, + 244, 6, 0, 0, 112, 0, + 0, 0, 8, 7, 0, 0, + 112, 0, 0, 0, 32, 7, 0, 0, 112, 0, 0, 0, - 44, 7, 0, 0, 117, 0, - 0, 0, 68, 7, 0, 0, - 112, 0, 0, 0, 84, 7, + 56, 7, 0, 0, 117, 0, + 0, 0, 80, 7, 0, 0, + 112, 0, 0, 0, 96, 7, 0, 0, 112, 0, 0, 0, - 104, 7, 0, 0, 112, 0, - 0, 0, 124, 7, 0, 0, - 112, 0, 0, 0, 148, 7, + 116, 7, 0, 0, 112, 0, + 0, 0, 136, 7, 0, 0, + 112, 0, 0, 0, 160, 7, 0, 0, 112, 0, 0, 0, - 172, 7, 0, 0, 112, 0, - 0, 0, 196, 7, 0, 0, - 112, 0, 0, 0, 220, 7, + 184, 7, 0, 0, 112, 0, + 0, 0, 208, 7, 0, 0, + 112, 0, 0, 0, 232, 7, 0, 0, 112, 0, 0, 0, - 244, 7, 0, 0, 117, 0, - 0, 0, 12, 8, 0, 0, - 117, 0, 0, 0, 28, 8, + 0, 8, 0, 0, 117, 0, + 0, 0, 24, 8, 0, 0, + 117, 0, 0, 0, 40, 8, 0, 0, 115, 0, 0, 0, - 44, 8, 0, 0, 116, 0, - 0, 0, 60, 8, 0, 0, - 115, 0, 0, 0, 76, 8, + 56, 8, 0, 0, 116, 0, + 0, 0, 72, 8, 0, 0, + 115, 0, 0, 0, 88, 8, 0, 0, 116, 0, 0, 0, - 92, 8, 0, 0, 115, 0, - 0, 0, 108, 8, 0, 0, - 116, 0, 0, 0, 124, 8, + 104, 8, 0, 0, 115, 0, + 0, 0, 120, 8, 0, 0, + 116, 0, 0, 0, 136, 8, 0, 0, 25, 1, 0, 0, - 140, 8, 0, 0, 28, 1, - 0, 0, 152, 8, 0, 0, - 29, 1, 0, 0, 168, 8, + 152, 8, 0, 0, 28, 1, + 0, 0, 164, 8, 0, 0, + 29, 1, 0, 0, 180, 8, 0, 0, 30, 1, 0, 0, - 184, 8, 0, 0, 30, 1, - 0, 0, 204, 8, 0, 0, - 30, 1, 0, 0, 220, 8, + 196, 8, 0, 0, 30, 1, + 0, 0, 216, 8, 0, 0, + 30, 1, 0, 0, 232, 8, 0, 0, 31, 1, 0, 0, - 236, 8, 0, 0, 31, 1, - 0, 0, 252, 8, 0, 0, - 31, 1, 0, 0, 12, 9, + 248, 8, 0, 0, 31, 1, + 0, 0, 8, 9, 0, 0, + 31, 1, 0, 0, 24, 9, 0, 0, 116, 0, 0, 0, - 28, 9, 0, 0, 25, 1, - 0, 0, 40, 9, 0, 0, - 25, 1, 0, 0, 56, 9, + 40, 9, 0, 0, 25, 1, + 0, 0, 52, 9, 0, 0, + 25, 1, 0, 0, 68, 9, 0, 0, 25, 1, 0, 0, - 72, 9, 0, 0, 33, 1, - 0, 0, 88, 9, 0, 0, - 25, 1, 0, 0, 104, 9, + 84, 9, 0, 0, 33, 1, + 0, 0, 100, 9, 0, 0, + 25, 1, 0, 0, 116, 9, 0, 0, 28, 1, 0, 0, - 116, 9, 0, 0, 28, 1, - 0, 0, 132, 9, 0, 0, - 28, 1, 0, 0, 148, 9, + 128, 9, 0, 0, 28, 1, + 0, 0, 144, 9, 0, 0, + 28, 1, 0, 0, 160, 9, 0, 0, 19, 1, 0, 0, - 164, 9, 0, 0, 19, 1, - 0, 0, 184, 9, 0, 0, - 117, 0, 0, 0, 196, 9, + 176, 9, 0, 0, 19, 1, + 0, 0, 196, 9, 0, 0, + 117, 0, 0, 0, 208, 9, 0, 0, 109, 97, 105, 110, 52, 66, 111, 110, 101, 115, 86, 99, 0, 112, 111, 115, @@ -499,7 +499,9 @@ const BYTE DGSLEffect_main4BonesVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 228, 0, 15, 160, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_mainVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_mainVc.inc index 1a21adff..9b088f79 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_mainVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLEffect_mainVc.inc @@ -56,7 +56,7 @@ dcl_texcoord3 v3 // vertex<11,12,13,14> dcl_texcoord4 v4 // vertex<15,16> -#line 150 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" +#line 150 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLEffect.fx" dp4 oPos.z, v0, c7 // ::mainVc<2> mul oT0, v3, c1 // ::mainVc<4,5,6,7> mad r0.xyz, v4.xyxw, c12.xxyw, c12.yyxw @@ -133,17 +133,17 @@ ret const BYTE DGSLEffect_mainVc[] = { - 68, 88, 66, 67, 72, 67, - 248, 97, 31, 192, 50, 24, - 77, 242, 183, 202, 121, 19, - 101, 76, 1, 0, 0, 0, - 228, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 120, 140, + 189, 222, 124, 120, 113, 219, + 87, 175, 95, 199, 3, 41, + 251, 116, 1, 0, 0, 0, + 240, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 64, 6, 0, 0, 68, 9, - 0, 0, 248, 9, 0, 0, - 65, 111, 110, 57, 8, 6, - 0, 0, 8, 6, 0, 0, - 0, 2, 254, 255, 164, 5, + 76, 6, 0, 0, 80, 9, + 0, 0, 4, 10, 0, 0, + 65, 111, 110, 57, 20, 6, + 0, 0, 20, 6, 0, 0, + 0, 2, 254, 255, 176, 5, 0, 0, 100, 0, 0, 0, 5, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, @@ -160,14 +160,14 @@ const BYTE DGSLEffect_mainVc[] = 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 3, 1, 68, 66, 85, 71, + 6, 1, 68, 66, 85, 71, 40, 0, 0, 0, 224, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 26, 0, 0, 0, 120, 0, 0, 0, 4, 0, 0, 0, 144, 3, 0, 0, - 72, 1, 0, 0, 67, 58, + 72, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -181,41 +181,41 @@ const BYTE DGSLEffect_mainVc[] = 83, 76, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 20, 4, + 0, 0, 255, 255, 32, 4, 0, 0, 0, 0, 255, 255, - 44, 4, 0, 0, 0, 0, - 255, 255, 56, 4, 0, 0, - 0, 0, 255, 255, 68, 4, + 56, 4, 0, 0, 0, 0, + 255, 255, 68, 4, 0, 0, + 0, 0, 255, 255, 80, 4, 0, 0, 0, 0, 255, 255, - 80, 4, 0, 0, 0, 0, - 255, 255, 92, 4, 0, 0, - 150, 0, 0, 0, 104, 4, + 92, 4, 0, 0, 0, 0, + 255, 255, 104, 4, 0, 0, + 150, 0, 0, 0, 116, 4, 0, 0, 151, 0, 0, 0, - 120, 4, 0, 0, 152, 0, - 0, 0, 136, 4, 0, 0, - 152, 0, 0, 0, 156, 4, + 132, 4, 0, 0, 152, 0, + 0, 0, 148, 4, 0, 0, + 152, 0, 0, 0, 168, 4, 0, 0, 152, 0, 0, 0, - 172, 4, 0, 0, 153, 0, - 0, 0, 188, 4, 0, 0, - 153, 0, 0, 0, 204, 4, + 184, 4, 0, 0, 153, 0, + 0, 0, 200, 4, 0, 0, + 153, 0, 0, 0, 216, 4, 0, 0, 153, 0, 0, 0, - 220, 4, 0, 0, 147, 0, - 0, 0, 236, 4, 0, 0, - 147, 0, 0, 0, 252, 4, + 232, 4, 0, 0, 147, 0, + 0, 0, 248, 4, 0, 0, + 147, 0, 0, 0, 8, 5, 0, 0, 147, 0, 0, 0, - 12, 5, 0, 0, 155, 0, - 0, 0, 28, 5, 0, 0, - 147, 0, 0, 0, 44, 5, + 24, 5, 0, 0, 155, 0, + 0, 0, 40, 5, 0, 0, + 147, 0, 0, 0, 56, 5, 0, 0, 150, 0, 0, 0, - 56, 5, 0, 0, 150, 0, - 0, 0, 72, 5, 0, 0, - 150, 0, 0, 0, 88, 5, + 68, 5, 0, 0, 150, 0, + 0, 0, 84, 5, 0, 0, + 150, 0, 0, 0, 100, 5, 0, 0, 143, 0, 0, 0, - 104, 5, 0, 0, 143, 0, - 0, 0, 124, 5, 0, 0, - 156, 0, 0, 0, 136, 5, + 116, 5, 0, 0, 143, 0, + 0, 0, 136, 5, 0, 0, + 156, 0, 0, 0, 148, 5, 0, 0, 157, 0, 0, 0, - 148, 5, 0, 0, 109, 97, + 160, 5, 0, 0, 109, 97, 105, 110, 86, 99, 0, 112, 111, 115, 0, 171, 1, 0, 3, 0, 1, 0, 4, 0, @@ -332,7 +332,9 @@ const BYTE DGSLEffect_mainVc[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 12, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_main.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_main.inc index e58b919d..ea5c7854 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_main.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_main.inc @@ -39,7 +39,7 @@ dcl t0 // pixel<4,5,6,7> dcl t2.xyz // pixel<10,11,12> -#line 99 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" +#line 99 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" nrm r0.xyz, t2 // ::worldNormal<0,1,2> #line 82 @@ -103,17 +103,17 @@ ret const BYTE DGSLLambert_main[] = { - 68, 88, 66, 67, 217, 104, - 24, 135, 161, 120, 240, 98, - 49, 130, 137, 15, 118, 241, - 187, 148, 1, 0, 0, 0, - 8, 9, 0, 0, 4, 0, + 68, 88, 66, 67, 37, 195, + 100, 143, 92, 130, 141, 2, + 35, 106, 227, 226, 67, 105, + 139, 53, 1, 0, 0, 0, + 20, 9, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 116, 5, 0, 0, 232, 7, - 0, 0, 212, 8, 0, 0, - 65, 111, 110, 57, 60, 5, - 0, 0, 60, 5, 0, 0, - 0, 2, 255, 255, 244, 4, + 128, 5, 0, 0, 244, 7, + 0, 0, 224, 8, 0, 0, + 65, 111, 110, 57, 72, 5, + 0, 0, 72, 5, 0, 0, + 0, 2, 255, 255, 0, 5, 0, 0, 72, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -125,7 +125,7 @@ const BYTE DGSLLambert_main[] = 0, 0, 1, 0, 9, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 240, 0, 68, 66, + 254, 255, 243, 0, 68, 66, 85, 71, 40, 0, 0, 0, 148, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -133,7 +133,7 @@ const BYTE DGSLLambert_main[] = 0, 0, 124, 0, 0, 0, 7, 0, 0, 0, 8, 3, 0, 0, 252, 1, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -147,31 +147,31 @@ const BYTE DGSLLambert_main[] = 109, 98, 101, 114, 116, 46, 104, 108, 115, 108, 0, 171, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 200, 3, + 0, 0, 255, 255, 212, 3, 0, 0, 0, 0, 255, 255, - 212, 3, 0, 0, 99, 0, - 0, 0, 224, 3, 0, 0, - 82, 0, 0, 0, 236, 3, + 224, 3, 0, 0, 99, 0, + 0, 0, 236, 3, 0, 0, + 82, 0, 0, 0, 248, 3, 0, 0, 83, 0, 0, 0, - 252, 3, 0, 0, 83, 0, - 0, 0, 12, 4, 0, 0, - 105, 0, 0, 0, 28, 4, + 8, 4, 0, 0, 83, 0, + 0, 0, 24, 4, 0, 0, + 105, 0, 0, 0, 40, 4, 0, 0, 105, 0, 0, 0, - 40, 4, 0, 0, 82, 0, - 0, 0, 60, 4, 0, 0, - 83, 0, 0, 0, 76, 4, + 52, 4, 0, 0, 82, 0, + 0, 0, 72, 4, 0, 0, + 83, 0, 0, 0, 88, 4, 0, 0, 105, 0, 0, 0, - 92, 4, 0, 0, 82, 0, - 0, 0, 112, 4, 0, 0, - 82, 0, 0, 0, 128, 4, + 104, 4, 0, 0, 82, 0, + 0, 0, 124, 4, 0, 0, + 82, 0, 0, 0, 140, 4, 0, 0, 83, 0, 0, 0, - 144, 4, 0, 0, 83, 0, - 0, 0, 160, 4, 0, 0, - 105, 0, 0, 0, 176, 4, + 156, 4, 0, 0, 83, 0, + 0, 0, 172, 4, 0, 0, + 105, 0, 0, 0, 188, 4, 0, 0, 105, 0, 0, 0, - 196, 4, 0, 0, 108, 0, - 0, 0, 216, 4, 0, 0, - 108, 0, 0, 0, 228, 4, + 208, 4, 0, 0, 108, 0, + 0, 0, 228, 4, 0, 0, + 108, 0, 0, 0, 240, 4, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, @@ -285,7 +285,9 @@ const BYTE DGSLLambert_main[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTk.inc index 0600eb94..b95522ff 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTk.inc @@ -40,7 +40,7 @@ dcl t0 // pixel<4,5,6,7> dcl t2.xyz // pixel<10,11,12> -#line 130 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" +#line 130 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" mul r0.w, t0.w, t0.w cmp r0, -r0.w, c10.x, c10.y texkill r0 @@ -115,17 +115,17 @@ ret const BYTE DGSLLambert_mainTk[] = { - 68, 88, 66, 67, 49, 185, - 15, 251, 73, 181, 30, 50, - 96, 92, 73, 219, 218, 231, - 168, 206, 1, 0, 0, 0, - 148, 9, 0, 0, 4, 0, + 68, 88, 66, 67, 134, 210, + 1, 93, 103, 30, 65, 51, + 37, 231, 17, 162, 11, 219, + 81, 130, 1, 0, 0, 0, + 160, 9, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 216, 5, 0, 0, 116, 8, - 0, 0, 96, 9, 0, 0, - 65, 111, 110, 57, 160, 5, - 0, 0, 160, 5, 0, 0, - 0, 2, 255, 255, 88, 5, + 228, 5, 0, 0, 128, 8, + 0, 0, 108, 9, 0, 0, + 65, 111, 110, 57, 172, 5, + 0, 0, 172, 5, 0, 0, + 0, 2, 255, 255, 100, 5, 0, 0, 72, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -137,7 +137,7 @@ const BYTE DGSLLambert_mainTk[] = 0, 0, 1, 0, 9, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 248, 0, 68, 66, + 254, 255, 251, 0, 68, 66, 85, 71, 40, 0, 0, 0, 180, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -145,7 +145,7 @@ const BYTE DGSLLambert_mainTk[] = 0, 0, 124, 0, 0, 0, 7, 0, 0, 0, 40, 3, 0, 0, 28, 2, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -159,37 +159,37 @@ const BYTE DGSLLambert_mainTk[] = 109, 98, 101, 114, 116, 46, 104, 108, 115, 108, 0, 171, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 232, 3, + 0, 0, 255, 255, 244, 3, 0, 0, 0, 0, 255, 255, - 0, 4, 0, 0, 0, 0, - 255, 255, 12, 4, 0, 0, - 130, 0, 0, 0, 24, 4, + 12, 4, 0, 0, 0, 0, + 255, 255, 24, 4, 0, 0, + 130, 0, 0, 0, 36, 4, 0, 0, 130, 0, 0, 0, - 40, 4, 0, 0, 130, 0, - 0, 0, 60, 4, 0, 0, - 118, 0, 0, 0, 68, 4, + 52, 4, 0, 0, 130, 0, + 0, 0, 72, 4, 0, 0, + 118, 0, 0, 0, 80, 4, 0, 0, 82, 0, 0, 0, - 80, 4, 0, 0, 83, 0, - 0, 0, 96, 4, 0, 0, - 83, 0, 0, 0, 112, 4, + 92, 4, 0, 0, 83, 0, + 0, 0, 108, 4, 0, 0, + 83, 0, 0, 0, 124, 4, 0, 0, 124, 0, 0, 0, - 128, 4, 0, 0, 124, 0, - 0, 0, 140, 4, 0, 0, - 82, 0, 0, 0, 160, 4, + 140, 4, 0, 0, 124, 0, + 0, 0, 152, 4, 0, 0, + 82, 0, 0, 0, 172, 4, 0, 0, 83, 0, 0, 0, - 176, 4, 0, 0, 124, 0, - 0, 0, 192, 4, 0, 0, - 82, 0, 0, 0, 212, 4, + 188, 4, 0, 0, 124, 0, + 0, 0, 204, 4, 0, 0, + 82, 0, 0, 0, 224, 4, 0, 0, 83, 0, 0, 0, - 228, 4, 0, 0, 124, 0, - 0, 0, 244, 4, 0, 0, - 82, 0, 0, 0, 8, 5, + 240, 4, 0, 0, 124, 0, + 0, 0, 0, 5, 0, 0, + 82, 0, 0, 0, 20, 5, 0, 0, 83, 0, 0, 0, - 24, 5, 0, 0, 124, 0, - 0, 0, 40, 5, 0, 0, - 132, 0, 0, 0, 60, 5, + 36, 5, 0, 0, 124, 0, + 0, 0, 52, 5, 0, 0, + 132, 0, 0, 0, 72, 5, 0, 0, 132, 0, 0, 0, - 72, 5, 0, 0, 77, 97, + 84, 5, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, 101, 114, 105, 97, @@ -302,7 +302,9 @@ const BYTE DGSLLambert_mainTk[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 10, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTx.inc index 34ef87c6..9ca65796 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTx.inc @@ -48,7 +48,7 @@ dcl t2.xyz // pixel<10,11,12> dcl_2d s0 -#line 149 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" +#line 149 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" texld r0, t1, s0 #line 139 @@ -121,17 +121,17 @@ ret const BYTE DGSLLambert_mainTx[] = { - 68, 88, 66, 67, 2, 83, - 250, 55, 168, 31, 166, 40, - 181, 24, 99, 4, 43, 67, - 37, 218, 1, 0, 0, 0, - 52, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 220, 108, + 222, 37, 85, 168, 128, 185, + 161, 109, 49, 214, 180, 70, + 18, 191, 1, 0, 0, 0, + 64, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 48, 6, 0, 0, 20, 9, - 0, 0, 0, 10, 0, 0, - 65, 111, 110, 57, 248, 5, - 0, 0, 248, 5, 0, 0, - 0, 2, 255, 255, 172, 5, + 60, 6, 0, 0, 32, 9, + 0, 0, 12, 10, 0, 0, + 65, 111, 110, 57, 4, 6, + 0, 0, 4, 6, 0, 0, + 0, 2, 255, 255, 184, 5, 0, 0, 76, 0, 0, 0, 3, 0, 40, 0, 0, 0, 76, 0, 0, 0, 76, 0, @@ -144,14 +144,14 @@ const BYTE DGSLLambert_mainTx[] = 1, 0, 9, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 15, 1, 68, 66, 85, 71, + 18, 1, 68, 66, 85, 71, 40, 0, 0, 0, 16, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0, 0, 23, 0, 0, 0, 124, 0, 0, 0, 9, 0, 0, 0, 92, 3, 0, 0, - 68, 2, 0, 0, 67, 58, + 68, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -166,36 +166,36 @@ const BYTE DGSLLambert_mainTx[] = 101, 114, 116, 46, 104, 108, 115, 108, 0, 171, 171, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 68, 4, 0, 0, - 0, 0, 255, 255, 80, 4, + 255, 255, 80, 4, 0, 0, + 0, 0, 255, 255, 92, 4, 0, 0, 0, 0, 255, 255, - 92, 4, 0, 0, 0, 0, - 255, 255, 104, 4, 0, 0, - 149, 0, 0, 0, 116, 4, + 104, 4, 0, 0, 0, 0, + 255, 255, 116, 4, 0, 0, + 149, 0, 0, 0, 128, 4, 0, 0, 139, 0, 0, 0, - 132, 4, 0, 0, 82, 0, - 0, 0, 144, 4, 0, 0, - 83, 0, 0, 0, 160, 4, + 144, 4, 0, 0, 82, 0, + 0, 0, 156, 4, 0, 0, + 83, 0, 0, 0, 172, 4, 0, 0, 83, 0, 0, 0, - 176, 4, 0, 0, 145, 0, - 0, 0, 192, 4, 0, 0, - 145, 0, 0, 0, 204, 4, + 188, 4, 0, 0, 145, 0, + 0, 0, 204, 4, 0, 0, + 145, 0, 0, 0, 216, 4, 0, 0, 82, 0, 0, 0, - 224, 4, 0, 0, 83, 0, - 0, 0, 240, 4, 0, 0, - 145, 0, 0, 0, 0, 5, + 236, 4, 0, 0, 83, 0, + 0, 0, 252, 4, 0, 0, + 145, 0, 0, 0, 12, 5, 0, 0, 82, 0, 0, 0, - 20, 5, 0, 0, 82, 0, - 0, 0, 36, 5, 0, 0, - 83, 0, 0, 0, 52, 5, + 32, 5, 0, 0, 82, 0, + 0, 0, 48, 5, 0, 0, + 83, 0, 0, 0, 64, 5, 0, 0, 83, 0, 0, 0, - 68, 5, 0, 0, 145, 0, - 0, 0, 84, 5, 0, 0, - 145, 0, 0, 0, 104, 5, + 80, 5, 0, 0, 145, 0, + 0, 0, 96, 5, 0, 0, + 145, 0, 0, 0, 116, 5, 0, 0, 149, 0, 0, 0, - 124, 5, 0, 0, 150, 0, - 0, 0, 140, 5, 0, 0, - 149, 0, 0, 0, 156, 5, + 136, 5, 0, 0, 150, 0, + 0, 0, 152, 5, 0, 0, + 149, 0, 0, 0, 168, 5, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, @@ -324,7 +324,9 @@ const BYTE DGSLLambert_mainTx[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTxTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTxTk.inc index ed82216e..be554844 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTxTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLLambert_mainTxTk.inc @@ -49,7 +49,7 @@ dcl t2.xyz // pixel<10,11,12> dcl_2d s0 -#line 170 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" +#line 170 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLLambert.hlsl" texld r0, t1, s0 mul r1.w, r0.w, t0.w // ::local5<0> @@ -136,17 +136,17 @@ ret const BYTE DGSLLambert_mainTxTk[] = { - 68, 88, 66, 67, 128, 125, - 248, 122, 94, 37, 149, 31, - 121, 205, 195, 201, 166, 72, - 161, 102, 1, 0, 0, 0, - 216, 10, 0, 0, 4, 0, + 68, 88, 66, 67, 176, 76, + 120, 115, 250, 116, 224, 21, + 189, 0, 217, 169, 115, 235, + 53, 1, 1, 0, 0, 0, + 228, 10, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 152, 6, 0, 0, 184, 9, - 0, 0, 164, 10, 0, 0, - 65, 111, 110, 57, 96, 6, - 0, 0, 96, 6, 0, 0, - 0, 2, 255, 255, 20, 6, + 164, 6, 0, 0, 196, 9, + 0, 0, 176, 10, 0, 0, + 65, 111, 110, 57, 108, 6, + 0, 0, 108, 6, 0, 0, + 0, 2, 255, 255, 32, 6, 0, 0, 76, 0, 0, 0, 3, 0, 40, 0, 0, 0, 76, 0, 0, 0, 76, 0, @@ -159,14 +159,14 @@ const BYTE DGSLLambert_mainTxTk[] = 1, 0, 9, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 24, 1, 68, 66, 85, 71, + 27, 1, 68, 66, 85, 71, 40, 0, 0, 0, 52, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0, 0, 27, 0, 0, 0, 124, 0, 0, 0, 9, 0, 0, 0, 128, 3, 0, 0, - 100, 2, 0, 0, 67, 58, + 100, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -181,42 +181,42 @@ const BYTE DGSLLambert_mainTxTk[] = 101, 114, 116, 46, 104, 108, 115, 108, 0, 171, 171, 171, 40, 0, 0, 0, 0, 0, - 255, 255, 104, 4, 0, 0, - 0, 0, 255, 255, 128, 4, + 255, 255, 116, 4, 0, 0, + 0, 0, 255, 255, 140, 4, 0, 0, 0, 0, 255, 255, - 140, 4, 0, 0, 0, 0, - 255, 255, 152, 4, 0, 0, - 0, 0, 255, 255, 164, 4, + 152, 4, 0, 0, 0, 0, + 255, 255, 164, 4, 0, 0, + 0, 0, 255, 255, 176, 4, 0, 0, 170, 0, 0, 0, - 176, 4, 0, 0, 171, 0, - 0, 0, 192, 4, 0, 0, - 174, 0, 0, 0, 208, 4, + 188, 4, 0, 0, 171, 0, + 0, 0, 204, 4, 0, 0, + 174, 0, 0, 0, 220, 4, 0, 0, 174, 0, 0, 0, - 224, 4, 0, 0, 174, 0, - 0, 0, 244, 4, 0, 0, - 160, 0, 0, 0, 252, 4, + 236, 4, 0, 0, 174, 0, + 0, 0, 0, 5, 0, 0, + 160, 0, 0, 0, 8, 5, 0, 0, 82, 0, 0, 0, - 8, 5, 0, 0, 83, 0, - 0, 0, 24, 5, 0, 0, - 83, 0, 0, 0, 40, 5, + 20, 5, 0, 0, 83, 0, + 0, 0, 36, 5, 0, 0, + 83, 0, 0, 0, 52, 5, 0, 0, 166, 0, 0, 0, - 56, 5, 0, 0, 166, 0, - 0, 0, 68, 5, 0, 0, - 82, 0, 0, 0, 88, 5, + 68, 5, 0, 0, 166, 0, + 0, 0, 80, 5, 0, 0, + 82, 0, 0, 0, 100, 5, 0, 0, 83, 0, 0, 0, - 104, 5, 0, 0, 166, 0, - 0, 0, 120, 5, 0, 0, - 82, 0, 0, 0, 140, 5, + 116, 5, 0, 0, 166, 0, + 0, 0, 132, 5, 0, 0, + 82, 0, 0, 0, 152, 5, 0, 0, 83, 0, 0, 0, - 156, 5, 0, 0, 166, 0, - 0, 0, 172, 5, 0, 0, - 82, 0, 0, 0, 192, 5, + 168, 5, 0, 0, 166, 0, + 0, 0, 184, 5, 0, 0, + 82, 0, 0, 0, 204, 5, 0, 0, 83, 0, 0, 0, - 208, 5, 0, 0, 166, 0, - 0, 0, 224, 5, 0, 0, - 170, 0, 0, 0, 244, 5, + 220, 5, 0, 0, 166, 0, + 0, 0, 236, 5, 0, 0, + 170, 0, 0, 0, 0, 6, 0, 0, 176, 0, 0, 0, - 4, 6, 0, 0, 77, 97, + 16, 6, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, 101, 114, 105, 97, @@ -345,7 +345,9 @@ const BYTE DGSLLambert_mainTxTk[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 10, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_main.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_main.inc index 72ede18b..f09a17b3 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_main.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_main.inc @@ -44,7 +44,7 @@ dcl t2.xyz // pixel<10,11,12> dcl t4.xyz // pixel<16,17,18> -#line 104 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" +#line 104 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" mov r0.xyz, c1 // MaterialVars::MaterialSpecular<0,1,2> mul r1.xyz, r0, c4 mul r2.xyz, r0, c5 @@ -179,17 +179,17 @@ ret const BYTE DGSLPhong_main[] = { - 68, 88, 66, 67, 17, 77, - 112, 60, 162, 43, 70, 93, - 242, 209, 41, 52, 161, 117, - 224, 183, 1, 0, 0, 0, - 8, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 145, 34, + 57, 62, 135, 230, 35, 7, + 22, 11, 189, 127, 214, 251, + 196, 212, 1, 0, 0, 0, + 20, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 180, 9, 0, 0, 232, 15, - 0, 0, 212, 16, 0, 0, - 65, 111, 110, 57, 124, 9, - 0, 0, 124, 9, 0, 0, - 0, 2, 255, 255, 16, 9, + 192, 9, 0, 0, 244, 15, + 0, 0, 224, 16, 0, 0, + 65, 111, 110, 57, 136, 9, + 0, 0, 136, 9, 0, 0, + 0, 2, 255, 255, 28, 9, 0, 0, 108, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -207,7 +207,7 @@ const BYTE DGSLPhong_main[] = 0, 0, 1, 0, 13, 0, 3, 0, 10, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 144, 1, 68, 66, + 254, 255, 147, 1, 68, 66, 85, 71, 40, 0, 0, 0, 20, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -215,7 +215,7 @@ const BYTE DGSLPhong_main[] = 0, 0, 120, 0, 0, 0, 14, 0, 0, 0, 252, 4, 0, 0, 36, 3, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -229,65 +229,65 @@ const BYTE DGSLPhong_main[] = 111, 110, 103, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, 0, 0, 255, 255, - 72, 6, 0, 0, 0, 0, - 255, 255, 96, 6, 0, 0, - 0, 0, 255, 255, 108, 6, + 84, 6, 0, 0, 0, 0, + 255, 255, 108, 6, 0, 0, + 0, 0, 255, 255, 120, 6, 0, 0, 0, 0, 255, 255, - 120, 6, 0, 0, 104, 0, - 0, 0, 132, 6, 0, 0, - 104, 0, 0, 0, 144, 6, + 132, 6, 0, 0, 104, 0, + 0, 0, 144, 6, 0, 0, + 104, 0, 0, 0, 156, 6, 0, 0, 104, 0, 0, 0, - 160, 6, 0, 0, 122, 0, - 0, 0, 176, 6, 0, 0, - 122, 0, 0, 0, 192, 6, + 172, 6, 0, 0, 122, 0, + 0, 0, 188, 6, 0, 0, + 122, 0, 0, 0, 204, 6, 0, 0, 101, 0, 0, 0, - 204, 6, 0, 0, 101, 0, - 0, 0, 224, 6, 0, 0, - 121, 0, 0, 0, 236, 6, + 216, 6, 0, 0, 101, 0, + 0, 0, 236, 6, 0, 0, + 121, 0, 0, 0, 248, 6, 0, 0, 102, 0, 0, 0, - 248, 6, 0, 0, 103, 0, - 0, 0, 8, 7, 0, 0, - 103, 0, 0, 0, 20, 7, + 4, 7, 0, 0, 103, 0, + 0, 0, 20, 7, 0, 0, + 103, 0, 0, 0, 32, 7, 0, 0, 103, 0, 0, 0, - 36, 7, 0, 0, 103, 0, - 0, 0, 52, 7, 0, 0, - 104, 0, 0, 0, 68, 7, + 48, 7, 0, 0, 103, 0, + 0, 0, 64, 7, 0, 0, + 104, 0, 0, 0, 80, 7, 0, 0, 101, 0, 0, 0, - 84, 7, 0, 0, 101, 0, - 0, 0, 104, 7, 0, 0, - 101, 0, 0, 0, 124, 7, + 96, 7, 0, 0, 101, 0, + 0, 0, 116, 7, 0, 0, + 101, 0, 0, 0, 136, 7, 0, 0, 102, 0, 0, 0, - 136, 7, 0, 0, 103, 0, - 0, 0, 152, 7, 0, 0, - 103, 0, 0, 0, 168, 7, + 148, 7, 0, 0, 103, 0, + 0, 0, 164, 7, 0, 0, + 103, 0, 0, 0, 180, 7, 0, 0, 101, 0, 0, 0, - 184, 7, 0, 0, 102, 0, - 0, 0, 196, 7, 0, 0, - 103, 0, 0, 0, 212, 7, + 196, 7, 0, 0, 102, 0, + 0, 0, 208, 7, 0, 0, + 103, 0, 0, 0, 224, 7, 0, 0, 103, 0, 0, 0, - 228, 7, 0, 0, 130, 0, - 0, 0, 244, 7, 0, 0, - 104, 0, 0, 0, 8, 8, + 240, 7, 0, 0, 130, 0, + 0, 0, 0, 8, 0, 0, + 104, 0, 0, 0, 20, 8, 0, 0, 130, 0, 0, 0, - 24, 8, 0, 0, 82, 0, - 0, 0, 44, 8, 0, 0, - 83, 0, 0, 0, 60, 8, + 36, 8, 0, 0, 82, 0, + 0, 0, 56, 8, 0, 0, + 83, 0, 0, 0, 72, 8, 0, 0, 83, 0, 0, 0, - 76, 8, 0, 0, 129, 0, - 0, 0, 92, 8, 0, 0, - 129, 0, 0, 0, 104, 8, + 88, 8, 0, 0, 129, 0, + 0, 0, 104, 8, 0, 0, + 129, 0, 0, 0, 116, 8, 0, 0, 82, 0, 0, 0, - 124, 8, 0, 0, 82, 0, - 0, 0, 140, 8, 0, 0, - 83, 0, 0, 0, 156, 8, + 136, 8, 0, 0, 82, 0, + 0, 0, 152, 8, 0, 0, + 83, 0, 0, 0, 168, 8, 0, 0, 83, 0, 0, 0, - 172, 8, 0, 0, 129, 0, - 0, 0, 188, 8, 0, 0, - 129, 0, 0, 0, 208, 8, + 184, 8, 0, 0, 129, 0, + 0, 0, 200, 8, 0, 0, + 129, 0, 0, 0, 220, 8, 0, 0, 134, 0, 0, 0, - 228, 8, 0, 0, 134, 0, - 0, 0, 244, 8, 0, 0, - 134, 0, 0, 0, 0, 9, + 240, 8, 0, 0, 134, 0, + 0, 0, 0, 9, 0, 0, + 134, 0, 0, 0, 12, 9, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, @@ -474,7 +474,9 @@ const BYTE DGSLPhong_main[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 23, 183, 209, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTk.inc index c37e2340..aa9148ba 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTk.inc @@ -44,7 +44,7 @@ dcl t2.xyz // pixel<10,11,12> dcl t4.xyz // pixel<16,17,18> -#line 158 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" +#line 158 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" mul r0.w, t0.w, t0.w cmp r0, -r0.w, c13.x, c13.y texkill r0 @@ -192,17 +192,17 @@ ret const BYTE DGSLPhong_mainTk[] = { - 68, 88, 66, 67, 51, 165, - 242, 85, 14, 19, 213, 109, - 6, 209, 238, 155, 101, 203, - 99, 253, 1, 0, 0, 0, - 44, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 244, 206, + 153, 139, 237, 11, 126, 5, + 194, 150, 126, 42, 156, 90, + 218, 1, 1, 0, 0, 0, + 56, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 176, 9, 0, 0, 12, 16, - 0, 0, 248, 16, 0, 0, - 65, 111, 110, 57, 120, 9, - 0, 0, 120, 9, 0, 0, - 0, 2, 255, 255, 12, 9, + 188, 9, 0, 0, 24, 16, + 0, 0, 4, 17, 0, 0, + 65, 111, 110, 57, 132, 9, + 0, 0, 132, 9, 0, 0, + 0, 2, 255, 255, 24, 9, 0, 0, 108, 0, 0, 0, 6, 0, 36, 0, 0, 0, 108, 0, 0, 0, 108, 0, @@ -220,7 +220,7 @@ const BYTE DGSLPhong_mainTk[] = 0, 0, 1, 0, 13, 0, 3, 0, 10, 0, 0, 0, 0, 0, 0, 2, 255, 255, - 254, 255, 132, 1, 68, 66, + 254, 255, 135, 1, 68, 66, 85, 71, 40, 0, 0, 0, 228, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -228,7 +228,7 @@ const BYTE DGSLPhong_mainTk[] = 0, 0, 120, 0, 0, 0, 13, 0, 0, 0, 224, 4, 0, 0, 8, 3, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -242,69 +242,69 @@ const BYTE DGSLPhong_mainTk[] = 111, 110, 103, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, 0, 0, 255, 255, - 24, 6, 0, 0, 0, 0, - 255, 255, 48, 6, 0, 0, - 0, 0, 255, 255, 60, 6, + 36, 6, 0, 0, 0, 0, + 255, 255, 60, 6, 0, 0, + 0, 0, 255, 255, 72, 6, 0, 0, 0, 0, 255, 255, - 72, 6, 0, 0, 158, 0, - 0, 0, 84, 6, 0, 0, - 158, 0, 0, 0, 100, 6, + 84, 6, 0, 0, 158, 0, + 0, 0, 96, 6, 0, 0, + 158, 0, 0, 0, 112, 6, 0, 0, 158, 0, 0, 0, - 120, 6, 0, 0, 144, 0, - 0, 0, 128, 6, 0, 0, - 144, 0, 0, 0, 144, 6, + 132, 6, 0, 0, 144, 0, + 0, 0, 140, 6, 0, 0, + 144, 0, 0, 0, 156, 6, 0, 0, 101, 0, 0, 0, - 156, 6, 0, 0, 101, 0, - 0, 0, 176, 6, 0, 0, - 143, 0, 0, 0, 188, 6, + 168, 6, 0, 0, 101, 0, + 0, 0, 188, 6, 0, 0, + 143, 0, 0, 0, 200, 6, 0, 0, 102, 0, 0, 0, - 200, 6, 0, 0, 82, 0, - 0, 0, 216, 6, 0, 0, - 83, 0, 0, 0, 232, 6, + 212, 6, 0, 0, 82, 0, + 0, 0, 228, 6, 0, 0, + 83, 0, 0, 0, 244, 6, 0, 0, 83, 0, 0, 0, - 248, 6, 0, 0, 151, 0, - 0, 0, 8, 7, 0, 0, - 151, 0, 0, 0, 20, 7, + 4, 7, 0, 0, 151, 0, + 0, 0, 20, 7, 0, 0, + 151, 0, 0, 0, 32, 7, 0, 0, 103, 0, 0, 0, - 40, 7, 0, 0, 103, 0, - 0, 0, 52, 7, 0, 0, - 82, 0, 0, 0, 68, 7, + 52, 7, 0, 0, 103, 0, + 0, 0, 64, 7, 0, 0, + 82, 0, 0, 0, 80, 7, 0, 0, 83, 0, 0, 0, - 84, 7, 0, 0, 151, 0, - 0, 0, 100, 7, 0, 0, - 82, 0, 0, 0, 120, 7, + 96, 7, 0, 0, 151, 0, + 0, 0, 112, 7, 0, 0, + 82, 0, 0, 0, 132, 7, 0, 0, 83, 0, 0, 0, - 136, 7, 0, 0, 151, 0, - 0, 0, 152, 7, 0, 0, - 103, 0, 0, 0, 172, 7, + 148, 7, 0, 0, 151, 0, + 0, 0, 164, 7, 0, 0, + 103, 0, 0, 0, 184, 7, 0, 0, 103, 0, 0, 0, - 188, 7, 0, 0, 101, 0, - 0, 0, 204, 7, 0, 0, - 101, 0, 0, 0, 224, 7, + 200, 7, 0, 0, 101, 0, + 0, 0, 216, 7, 0, 0, + 101, 0, 0, 0, 236, 7, 0, 0, 102, 0, 0, 0, - 236, 7, 0, 0, 103, 0, - 0, 0, 252, 7, 0, 0, - 103, 0, 0, 0, 12, 8, + 248, 7, 0, 0, 103, 0, + 0, 0, 8, 8, 0, 0, + 103, 0, 0, 0, 24, 8, 0, 0, 101, 0, 0, 0, - 28, 8, 0, 0, 101, 0, - 0, 0, 48, 8, 0, 0, - 102, 0, 0, 0, 60, 8, + 40, 8, 0, 0, 101, 0, + 0, 0, 60, 8, 0, 0, + 102, 0, 0, 0, 72, 8, 0, 0, 103, 0, 0, 0, - 76, 8, 0, 0, 103, 0, - 0, 0, 92, 8, 0, 0, - 104, 0, 0, 0, 108, 8, + 88, 8, 0, 0, 103, 0, + 0, 0, 104, 8, 0, 0, + 104, 0, 0, 0, 120, 8, 0, 0, 104, 0, 0, 0, - 120, 8, 0, 0, 104, 0, - 0, 0, 136, 8, 0, 0, - 104, 0, 0, 0, 152, 8, + 132, 8, 0, 0, 104, 0, + 0, 0, 148, 8, 0, 0, + 104, 0, 0, 0, 164, 8, 0, 0, 152, 0, 0, 0, - 168, 8, 0, 0, 104, 0, - 0, 0, 188, 8, 0, 0, - 152, 0, 0, 0, 204, 8, + 180, 8, 0, 0, 104, 0, + 0, 0, 200, 8, 0, 0, + 152, 0, 0, 0, 216, 8, 0, 0, 156, 0, 0, 0, - 224, 8, 0, 0, 160, 0, - 0, 0, 240, 8, 0, 0, - 160, 0, 0, 0, 252, 8, + 236, 8, 0, 0, 160, 0, + 0, 0, 252, 8, 0, 0, + 160, 0, 0, 0, 8, 9, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, @@ -479,7 +479,9 @@ const BYTE DGSLPhong_mainTk[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 23, 183, 209, 56, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTx.inc index 170dfd66..22809b0f 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTx.inc @@ -53,7 +53,7 @@ dcl t4.xyz // pixel<16,17,18> dcl_2d s0 -#line 180 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" +#line 180 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" texld r0, t1, s0 #line 104 @@ -195,17 +195,17 @@ ret const BYTE DGSLPhong_mainTx[] = { - 68, 88, 66, 67, 245, 121, - 96, 181, 252, 90, 214, 151, - 2, 228, 95, 163, 213, 199, - 33, 130, 1, 0, 0, 0, - 212, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 203, 248, + 171, 255, 80, 127, 38, 210, + 88, 59, 105, 224, 187, 69, + 13, 245, 1, 0, 0, 0, + 224, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 36, 10, 0, 0, 180, 16, - 0, 0, 160, 17, 0, 0, - 65, 111, 110, 57, 236, 9, - 0, 0, 236, 9, 0, 0, - 0, 2, 255, 255, 124, 9, + 48, 10, 0, 0, 192, 16, + 0, 0, 172, 17, 0, 0, + 65, 111, 110, 57, 248, 9, + 0, 0, 248, 9, 0, 0, + 0, 2, 255, 255, 136, 9, 0, 0, 112, 0, 0, 0, 6, 0, 40, 0, 0, 0, 112, 0, 0, 0, 112, 0, @@ -224,14 +224,14 @@ const BYTE DGSLPhong_mainTx[] = 1, 0, 13, 0, 3, 0, 10, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 159, 1, 68, 66, 85, 71, + 162, 1, 68, 66, 85, 71, 40, 0, 0, 0, 80, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 48, 0, 0, 0, 120, 0, 0, 0, 15, 0, 0, 0, 36, 5, 0, 0, - 100, 3, 0, 0, 67, 58, + 100, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -245,70 +245,70 @@ const BYTE DGSLPhong_mainTx[] = 83, 76, 80, 104, 111, 110, 103, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 132, 6, + 0, 0, 255, 255, 144, 6, 0, 0, 0, 0, 255, 255, - 156, 6, 0, 0, 0, 0, - 255, 255, 168, 6, 0, 0, - 0, 0, 255, 255, 180, 6, + 168, 6, 0, 0, 0, 0, + 255, 255, 180, 6, 0, 0, + 0, 0, 255, 255, 192, 6, 0, 0, 0, 0, 255, 255, - 192, 6, 0, 0, 0, 0, - 255, 255, 204, 6, 0, 0, - 180, 0, 0, 0, 216, 6, + 204, 6, 0, 0, 0, 0, + 255, 255, 216, 6, 0, 0, + 180, 0, 0, 0, 228, 6, 0, 0, 104, 0, 0, 0, - 232, 6, 0, 0, 104, 0, - 0, 0, 244, 6, 0, 0, - 104, 0, 0, 0, 4, 7, + 244, 6, 0, 0, 104, 0, + 0, 0, 0, 7, 0, 0, + 104, 0, 0, 0, 16, 7, 0, 0, 168, 0, 0, 0, - 20, 7, 0, 0, 168, 0, - 0, 0, 36, 7, 0, 0, - 101, 0, 0, 0, 48, 7, + 32, 7, 0, 0, 168, 0, + 0, 0, 48, 7, 0, 0, + 101, 0, 0, 0, 60, 7, 0, 0, 101, 0, 0, 0, - 68, 7, 0, 0, 167, 0, - 0, 0, 80, 7, 0, 0, - 102, 0, 0, 0, 92, 7, + 80, 7, 0, 0, 167, 0, + 0, 0, 92, 7, 0, 0, + 102, 0, 0, 0, 104, 7, 0, 0, 103, 0, 0, 0, - 108, 7, 0, 0, 103, 0, - 0, 0, 120, 7, 0, 0, - 103, 0, 0, 0, 136, 7, + 120, 7, 0, 0, 103, 0, + 0, 0, 132, 7, 0, 0, + 103, 0, 0, 0, 148, 7, 0, 0, 103, 0, 0, 0, - 152, 7, 0, 0, 104, 0, - 0, 0, 168, 7, 0, 0, - 101, 0, 0, 0, 184, 7, + 164, 7, 0, 0, 104, 0, + 0, 0, 180, 7, 0, 0, + 101, 0, 0, 0, 196, 7, 0, 0, 101, 0, 0, 0, - 204, 7, 0, 0, 101, 0, - 0, 0, 224, 7, 0, 0, - 102, 0, 0, 0, 236, 7, + 216, 7, 0, 0, 101, 0, + 0, 0, 236, 7, 0, 0, + 102, 0, 0, 0, 248, 7, 0, 0, 103, 0, 0, 0, - 252, 7, 0, 0, 103, 0, - 0, 0, 12, 8, 0, 0, - 101, 0, 0, 0, 28, 8, + 8, 8, 0, 0, 103, 0, + 0, 0, 24, 8, 0, 0, + 101, 0, 0, 0, 40, 8, 0, 0, 102, 0, 0, 0, - 40, 8, 0, 0, 103, 0, - 0, 0, 56, 8, 0, 0, - 103, 0, 0, 0, 72, 8, + 52, 8, 0, 0, 103, 0, + 0, 0, 68, 8, 0, 0, + 103, 0, 0, 0, 84, 8, 0, 0, 176, 0, 0, 0, - 88, 8, 0, 0, 104, 0, - 0, 0, 108, 8, 0, 0, - 176, 0, 0, 0, 124, 8, + 100, 8, 0, 0, 104, 0, + 0, 0, 120, 8, 0, 0, + 176, 0, 0, 0, 136, 8, 0, 0, 82, 0, 0, 0, - 144, 8, 0, 0, 83, 0, - 0, 0, 160, 8, 0, 0, - 83, 0, 0, 0, 176, 8, + 156, 8, 0, 0, 83, 0, + 0, 0, 172, 8, 0, 0, + 83, 0, 0, 0, 188, 8, 0, 0, 175, 0, 0, 0, - 192, 8, 0, 0, 175, 0, - 0, 0, 204, 8, 0, 0, - 82, 0, 0, 0, 224, 8, + 204, 8, 0, 0, 175, 0, + 0, 0, 216, 8, 0, 0, + 82, 0, 0, 0, 236, 8, 0, 0, 82, 0, 0, 0, - 240, 8, 0, 0, 83, 0, - 0, 0, 0, 9, 0, 0, - 83, 0, 0, 0, 16, 9, + 252, 8, 0, 0, 83, 0, + 0, 0, 12, 9, 0, 0, + 83, 0, 0, 0, 28, 9, 0, 0, 175, 0, 0, 0, - 32, 9, 0, 0, 175, 0, - 0, 0, 52, 9, 0, 0, - 180, 0, 0, 0, 72, 9, + 44, 9, 0, 0, 175, 0, + 0, 0, 64, 9, 0, 0, + 180, 0, 0, 0, 84, 9, 0, 0, 181, 0, 0, 0, - 92, 9, 0, 0, 180, 0, - 0, 0, 108, 9, 0, 0, + 104, 9, 0, 0, 180, 0, + 0, 0, 120, 9, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, 101, 114, @@ -500,7 +500,9 @@ const BYTE DGSLPhong_mainTx[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 23, 183, 209, 56, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTxTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTxTk.inc index 7cc98301..dc863c0e 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTxTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLPhong_mainTxTk.inc @@ -53,7 +53,7 @@ dcl t4.xyz // pixel<16,17,18> dcl_2d s0 -#line 204 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" +#line 204 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLPhong.hlsl" texld r0, t1, s0 mul r1.w, r0.w, t0.w // ::local6<0> @@ -209,17 +209,17 @@ ret const BYTE DGSLPhong_mainTxTk[] = { - 68, 88, 66, 67, 235, 167, - 128, 244, 246, 144, 158, 216, - 206, 36, 154, 226, 67, 2, - 231, 43, 1, 0, 0, 0, - 16, 18, 0, 0, 4, 0, + 68, 88, 66, 67, 217, 242, + 51, 158, 205, 76, 37, 171, + 125, 107, 245, 41, 148, 83, + 112, 124, 1, 0, 0, 0, + 28, 18, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 36, 10, 0, 0, 240, 16, - 0, 0, 220, 17, 0, 0, - 65, 111, 110, 57, 236, 9, - 0, 0, 236, 9, 0, 0, - 0, 2, 255, 255, 124, 9, + 48, 10, 0, 0, 252, 16, + 0, 0, 232, 17, 0, 0, + 65, 111, 110, 57, 248, 9, + 0, 0, 248, 9, 0, 0, + 0, 2, 255, 255, 136, 9, 0, 0, 112, 0, 0, 0, 6, 0, 40, 0, 0, 0, 112, 0, 0, 0, 112, 0, @@ -238,14 +238,14 @@ const BYTE DGSLPhong_mainTxTk[] = 1, 0, 13, 0, 3, 0, 10, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 148, 1, 68, 66, 85, 71, + 151, 1, 68, 66, 85, 71, 40, 0, 0, 0, 36, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 51, 0, 0, 0, 120, 0, 0, 0, 14, 0, 0, 0, 12, 5, 0, 0, - 72, 3, 0, 0, 67, 58, + 72, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -259,74 +259,74 @@ const BYTE DGSLPhong_mainTxTk[] = 83, 76, 80, 104, 111, 110, 103, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 88, 6, + 0, 0, 255, 255, 100, 6, 0, 0, 0, 0, 255, 255, - 112, 6, 0, 0, 0, 0, - 255, 255, 124, 6, 0, 0, - 0, 0, 255, 255, 136, 6, + 124, 6, 0, 0, 0, 0, + 255, 255, 136, 6, 0, 0, + 0, 0, 255, 255, 148, 6, 0, 0, 0, 0, 255, 255, - 148, 6, 0, 0, 0, 0, - 255, 255, 160, 6, 0, 0, - 204, 0, 0, 0, 172, 6, + 160, 6, 0, 0, 0, 0, + 255, 255, 172, 6, 0, 0, + 204, 0, 0, 0, 184, 6, 0, 0, 205, 0, 0, 0, - 188, 6, 0, 0, 208, 0, - 0, 0, 204, 6, 0, 0, - 208, 0, 0, 0, 220, 6, + 200, 6, 0, 0, 208, 0, + 0, 0, 216, 6, 0, 0, + 208, 0, 0, 0, 232, 6, 0, 0, 208, 0, 0, 0, - 240, 6, 0, 0, 192, 0, - 0, 0, 248, 6, 0, 0, - 192, 0, 0, 0, 8, 7, + 252, 6, 0, 0, 192, 0, + 0, 0, 4, 7, 0, 0, + 192, 0, 0, 0, 20, 7, 0, 0, 101, 0, 0, 0, - 20, 7, 0, 0, 101, 0, - 0, 0, 40, 7, 0, 0, - 191, 0, 0, 0, 52, 7, + 32, 7, 0, 0, 101, 0, + 0, 0, 52, 7, 0, 0, + 191, 0, 0, 0, 64, 7, 0, 0, 102, 0, 0, 0, - 64, 7, 0, 0, 82, 0, - 0, 0, 80, 7, 0, 0, - 83, 0, 0, 0, 96, 7, + 76, 7, 0, 0, 82, 0, + 0, 0, 92, 7, 0, 0, + 83, 0, 0, 0, 108, 7, 0, 0, 83, 0, 0, 0, - 112, 7, 0, 0, 199, 0, - 0, 0, 128, 7, 0, 0, - 199, 0, 0, 0, 140, 7, + 124, 7, 0, 0, 199, 0, + 0, 0, 140, 7, 0, 0, + 199, 0, 0, 0, 152, 7, 0, 0, 103, 0, 0, 0, - 160, 7, 0, 0, 103, 0, - 0, 0, 172, 7, 0, 0, - 82, 0, 0, 0, 188, 7, + 172, 7, 0, 0, 103, 0, + 0, 0, 184, 7, 0, 0, + 82, 0, 0, 0, 200, 7, 0, 0, 83, 0, 0, 0, - 204, 7, 0, 0, 199, 0, - 0, 0, 220, 7, 0, 0, - 82, 0, 0, 0, 240, 7, + 216, 7, 0, 0, 199, 0, + 0, 0, 232, 7, 0, 0, + 82, 0, 0, 0, 252, 7, 0, 0, 83, 0, 0, 0, - 0, 8, 0, 0, 199, 0, - 0, 0, 16, 8, 0, 0, - 103, 0, 0, 0, 36, 8, + 12, 8, 0, 0, 199, 0, + 0, 0, 28, 8, 0, 0, + 103, 0, 0, 0, 48, 8, 0, 0, 103, 0, 0, 0, - 52, 8, 0, 0, 101, 0, - 0, 0, 68, 8, 0, 0, - 101, 0, 0, 0, 88, 8, + 64, 8, 0, 0, 101, 0, + 0, 0, 80, 8, 0, 0, + 101, 0, 0, 0, 100, 8, 0, 0, 102, 0, 0, 0, - 100, 8, 0, 0, 103, 0, - 0, 0, 116, 8, 0, 0, - 103, 0, 0, 0, 132, 8, + 112, 8, 0, 0, 103, 0, + 0, 0, 128, 8, 0, 0, + 103, 0, 0, 0, 144, 8, 0, 0, 101, 0, 0, 0, - 148, 8, 0, 0, 101, 0, - 0, 0, 168, 8, 0, 0, - 102, 0, 0, 0, 180, 8, + 160, 8, 0, 0, 101, 0, + 0, 0, 180, 8, 0, 0, + 102, 0, 0, 0, 192, 8, 0, 0, 103, 0, 0, 0, - 196, 8, 0, 0, 103, 0, - 0, 0, 212, 8, 0, 0, - 104, 0, 0, 0, 228, 8, + 208, 8, 0, 0, 103, 0, + 0, 0, 224, 8, 0, 0, + 104, 0, 0, 0, 240, 8, 0, 0, 104, 0, 0, 0, - 240, 8, 0, 0, 104, 0, - 0, 0, 0, 9, 0, 0, - 104, 0, 0, 0, 16, 9, + 252, 8, 0, 0, 104, 0, + 0, 0, 12, 9, 0, 0, + 104, 0, 0, 0, 28, 9, 0, 0, 200, 0, 0, 0, - 32, 9, 0, 0, 104, 0, - 0, 0, 52, 9, 0, 0, - 200, 0, 0, 0, 68, 9, + 44, 9, 0, 0, 104, 0, + 0, 0, 64, 9, 0, 0, + 200, 0, 0, 0, 80, 9, 0, 0, 204, 0, 0, 0, - 88, 9, 0, 0, 210, 0, - 0, 0, 108, 9, 0, 0, + 100, 9, 0, 0, 210, 0, + 0, 0, 120, 9, 0, 0, 77, 97, 116, 101, 114, 105, 97, 108, 86, 97, 114, 115, 0, 77, 97, 116, 101, 114, @@ -507,7 +507,9 @@ const BYTE DGSLPhong_mainTxTk[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 13, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 23, 183, 209, 56, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_main.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_main.inc index 9e207110..1eff50c8 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_main.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_main.inc @@ -29,7 +29,7 @@ ps_2_0 dcl t0 // pixel<4,5,6,7> -#line 83 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" +#line 83 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" mov oC0, t0 // ::main<0,1,2,3> // approximately 1 instruction slot used @@ -43,23 +43,23 @@ ret const BYTE DGSLUnlit_main[] = { - 68, 88, 66, 67, 131, 172, - 120, 173, 112, 184, 143, 42, - 142, 197, 113, 141, 74, 250, - 229, 255, 1, 0, 0, 0, - 192, 3, 0, 0, 4, 0, + 68, 88, 66, 67, 61, 3, + 245, 70, 251, 216, 73, 233, + 53, 70, 10, 126, 162, 157, + 69, 231, 1, 0, 0, 0, + 204, 3, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 96, 2, 0, 0, 160, 2, - 0, 0, 140, 3, 0, 0, - 65, 111, 110, 57, 40, 2, - 0, 0, 40, 2, 0, 0, - 0, 2, 255, 255, 4, 2, + 108, 2, 0, 0, 172, 2, + 0, 0, 152, 3, 0, 0, + 65, 111, 110, 57, 52, 2, + 0, 0, 52, 2, 0, 0, + 0, 2, 255, 255, 16, 2, 0, 0, 36, 0, 0, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 2, 255, 255, - 254, 255, 120, 0, 68, 66, + 254, 255, 123, 0, 68, 66, 85, 71, 40, 0, 0, 0, 180, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -67,7 +67,7 @@ const BYTE DGSLUnlit_main[] = 0, 0, 120, 0, 0, 0, 2, 0, 0, 0, 140, 1, 0, 0, 136, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -81,8 +81,8 @@ const BYTE DGSLUnlit_main[] = 108, 105, 116, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, 0, 0, 255, 255, - 232, 1, 0, 0, 83, 0, - 0, 0, 244, 1, 0, 0, + 244, 1, 0, 0, 83, 0, + 0, 0, 0, 2, 0, 0, 109, 97, 105, 110, 0, 102, 114, 97, 103, 109, 101, 110, 116, 0, 171, 171, 1, 0, @@ -139,7 +139,9 @@ const BYTE DGSLUnlit_main[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 1, 0, 0, 2, 0, 8, 15, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTk.inc index fdcc6471..577d3710 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTk.inc @@ -30,7 +30,7 @@ def c0, -1, -0, 0, 0 dcl t0 // pixel<4,5,6,7> -#line 93 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" +#line 93 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" mul r0.w, t0.w, t0.w cmp r0, -r0.w, c0.x, c0.y texkill r0 @@ -51,23 +51,23 @@ ret const BYTE DGSLUnlit_mainTk[] = { - 68, 88, 66, 67, 245, 73, - 98, 112, 30, 115, 101, 94, - 153, 195, 39, 160, 72, 88, - 83, 207, 1, 0, 0, 0, - 116, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 22, 42, + 40, 87, 164, 245, 6, 218, + 239, 194, 64, 18, 252, 233, + 81, 172, 1, 0, 0, 0, + 128, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 228, 2, 0, 0, 84, 3, - 0, 0, 64, 4, 0, 0, - 65, 111, 110, 57, 172, 2, - 0, 0, 172, 2, 0, 0, - 0, 2, 255, 255, 136, 2, + 240, 2, 0, 0, 96, 3, + 0, 0, 76, 4, 0, 0, + 65, 111, 110, 57, 184, 2, + 0, 0, 184, 2, 0, 0, + 0, 2, 255, 255, 148, 2, 0, 0, 36, 0, 0, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 2, 255, 255, - 254, 255, 133, 0, 68, 66, + 254, 255, 136, 0, 68, 66, 85, 71, 40, 0, 0, 0, 232, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, @@ -75,7 +75,7 @@ const BYTE DGSLUnlit_mainTk[] = 0, 0, 120, 0, 0, 0, 2, 0, 0, 0, 192, 1, 0, 0, 176, 0, 0, 0, - 67, 58, 92, 65, 84, 71, + 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, @@ -89,15 +89,15 @@ const BYTE DGSLUnlit_mainTk[] = 108, 105, 116, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, 0, 0, 255, 255, - 28, 2, 0, 0, 0, 0, - 255, 255, 52, 2, 0, 0, - 93, 0, 0, 0, 64, 2, + 40, 2, 0, 0, 0, 0, + 255, 255, 64, 2, 0, 0, + 93, 0, 0, 0, 76, 2, 0, 0, 93, 0, 0, 0, - 80, 2, 0, 0, 93, 0, - 0, 0, 100, 2, 0, 0, - 95, 0, 0, 0, 108, 2, + 92, 2, 0, 0, 93, 0, + 0, 0, 112, 2, 0, 0, + 95, 0, 0, 0, 120, 2, 0, 0, 95, 0, 0, 0, - 120, 2, 0, 0, 109, 97, + 132, 2, 0, 0, 109, 97, 105, 110, 84, 107, 0, 102, 114, 97, 103, 109, 101, 110, 116, 0, 1, 0, 3, 0, @@ -156,7 +156,9 @@ const BYTE DGSLUnlit_mainTk[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 0, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTx.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTx.inc index 11b180b3..68e05ad1 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTx.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTx.inc @@ -38,7 +38,7 @@ dcl t1.xy // pixel<8,9> dcl_2d s0 -#line 117 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" +#line 117 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" texld r0, t1, s0 mul r1, r0, t0 // ::local3<0,1,2>, ::local4<0> mov oC0, r1 // ::mainTx<0,1,2,3> @@ -59,31 +59,31 @@ ret const BYTE DGSLUnlit_mainTx[] = { - 68, 88, 66, 67, 14, 132, - 199, 88, 131, 122, 131, 137, - 21, 243, 17, 86, 184, 232, - 27, 220, 1, 0, 0, 0, - 224, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 26, 91, + 239, 86, 147, 193, 19, 119, + 249, 89, 119, 177, 190, 203, + 224, 151, 1, 0, 0, 0, + 236, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 36, 3, 0, 0, 192, 3, - 0, 0, 172, 4, 0, 0, - 65, 111, 110, 57, 236, 2, - 0, 0, 236, 2, 0, 0, - 0, 2, 255, 255, 196, 2, + 48, 3, 0, 0, 204, 3, + 0, 0, 184, 4, 0, 0, + 65, 111, 110, 57, 248, 2, + 0, 0, 248, 2, 0, 0, + 0, 2, 255, 255, 208, 2, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 154, 0, 68, 66, 85, 71, + 157, 0, 68, 66, 85, 71, 40, 0, 0, 0, 60, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 120, 0, 0, 0, 4, 0, 0, 0, 236, 1, 0, 0, - 240, 0, 0, 0, 67, 58, + 240, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -97,14 +97,14 @@ const BYTE DGSLUnlit_mainTx[] = 83, 76, 85, 110, 108, 105, 116, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 112, 2, + 0, 0, 255, 255, 124, 2, 0, 0, 0, 0, 255, 255, - 124, 2, 0, 0, 0, 0, - 255, 255, 136, 2, 0, 0, - 117, 0, 0, 0, 148, 2, + 136, 2, 0, 0, 0, 0, + 255, 255, 148, 2, 0, 0, + 117, 0, 0, 0, 160, 2, 0, 0, 117, 0, 0, 0, - 164, 2, 0, 0, 117, 0, - 0, 0, 180, 2, 0, 0, + 176, 2, 0, 0, 117, 0, + 0, 0, 192, 2, 0, 0, 108, 111, 99, 97, 108, 51, 0, 171, 1, 0, 3, 0, 1, 0, 3, 0, 1, 0, @@ -178,7 +178,9 @@ const BYTE DGSLUnlit_mainTx[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTxTk.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTxTk.inc index f33ab326..6fd687c0 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTxTk.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DGSLUnlit_mainTxTk.inc @@ -39,7 +39,7 @@ dcl t1.xy // pixel<8,9> dcl_2d s0 -#line 144 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" +#line 144 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DGSLUnlit.hlsl" texld r0, t1, s0 mul r1.w, r0.w, t0.w // ::local4<0> @@ -74,31 +74,31 @@ ret const BYTE DGSLUnlit_mainTxTk[] = { - 68, 88, 66, 67, 163, 187, - 53, 119, 142, 182, 238, 196, - 183, 110, 204, 63, 193, 239, - 206, 55, 1, 0, 0, 0, - 184, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 214, 117, + 150, 240, 231, 235, 88, 117, + 64, 188, 40, 16, 6, 205, + 57, 246, 1, 0, 0, 0, + 196, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 164, 3, 0, 0, 152, 4, - 0, 0, 132, 5, 0, 0, - 65, 111, 110, 57, 108, 3, - 0, 0, 108, 3, 0, 0, - 0, 2, 255, 255, 68, 3, + 176, 3, 0, 0, 164, 4, + 0, 0, 144, 5, 0, 0, + 65, 111, 110, 57, 120, 3, + 0, 0, 120, 3, 0, 0, + 0, 2, 255, 255, 80, 3, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 165, 0, 68, 66, 85, 71, + 168, 0, 68, 66, 85, 71, 40, 0, 0, 0, 104, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 11, 0, 0, 0, 120, 0, 0, 0, 4, 0, 0, 0, 24, 2, 0, 0, - 24, 1, 0, 0, 67, 58, + 24, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -112,21 +112,21 @@ const BYTE DGSLUnlit_mainTxTk[] = 83, 76, 85, 110, 108, 105, 116, 46, 104, 108, 115, 108, 0, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 156, 2, + 0, 0, 255, 255, 168, 2, 0, 0, 0, 0, 255, 255, - 180, 2, 0, 0, 0, 0, - 255, 255, 192, 2, 0, 0, - 0, 0, 255, 255, 204, 2, + 192, 2, 0, 0, 0, 0, + 255, 255, 204, 2, 0, 0, + 0, 0, 255, 255, 216, 2, 0, 0, 144, 0, 0, 0, - 216, 2, 0, 0, 145, 0, - 0, 0, 232, 2, 0, 0, - 149, 0, 0, 0, 248, 2, + 228, 2, 0, 0, 145, 0, + 0, 0, 244, 2, 0, 0, + 149, 0, 0, 0, 4, 3, 0, 0, 149, 0, 0, 0, - 8, 3, 0, 0, 149, 0, - 0, 0, 28, 3, 0, 0, - 144, 0, 0, 0, 36, 3, + 20, 3, 0, 0, 149, 0, + 0, 0, 40, 3, 0, 0, + 144, 0, 0, 0, 48, 3, 0, 0, 151, 0, 0, 0, - 52, 3, 0, 0, 108, 111, + 64, 3, 0, 0, 108, 111, 99, 97, 108, 51, 0, 171, 1, 0, 3, 0, 1, 0, 3, 0, 1, 0, 0, 0, @@ -201,7 +201,9 @@ const BYTE DGSLUnlit_mainTxTk[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 0, 0, 15, 160, 0, 0, 128, 191, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc index 6442d1ee..e994fde3 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc @@ -45,7 +45,7 @@ dcl_2d s0 dcl_2d s1 -#line 98 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 98 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mov r0.xy, t2.wzyx texld r0, r0, s1 // ::overlay<0,1,2,3> texld r1, t2, s0 // ::color<0,1,2,3> @@ -55,7 +55,7 @@ mul r1, r1, c1 mul r0, r0, r1 // ::color<0,1,2,3> -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, c0, r0.w, -r0 mad r0.xyz, t1.w, r1, r0 // ApplyFog::color<0,1,2> mov oC0, r0 // ::PSDualTexture<0,1,2,3> @@ -87,17 +87,17 @@ ret const BYTE DualTextureEffect_PSDualTexture[] = { - 68, 88, 66, 67, 90, 48, - 60, 15, 10, 243, 234, 83, - 37, 109, 33, 173, 19, 116, - 245, 45, 1, 0, 0, 0, - 164, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 95, 47, + 113, 252, 51, 145, 165, 51, + 46, 143, 216, 187, 118, 48, + 155, 49, 1, 0, 0, 0, + 176, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 68, 4, 0, 0, 240, 5, - 0, 0, 112, 6, 0, 0, - 65, 111, 110, 57, 12, 4, - 0, 0, 12, 4, 0, 0, - 0, 2, 255, 255, 212, 3, + 80, 4, 0, 0, 252, 5, + 0, 0, 124, 6, 0, 0, + 65, 111, 110, 57, 24, 4, + 0, 0, 24, 4, 0, 0, + 0, 2, 255, 255, 224, 3, 0, 0, 56, 0, 0, 0, 1, 0, 44, 0, 0, 0, 56, 0, 0, 0, 56, 0, @@ -106,7 +106,7 @@ const BYTE DualTextureEffect_PSDualTexture[] = 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 255, 255, 254, 255, 185, 0, + 255, 255, 254, 255, 188, 0, 68, 66, 85, 71, 40, 0, 0, 0, 184, 2, 0, 0, 0, 0, 0, 0, 2, 0, @@ -114,7 +114,7 @@ const BYTE DualTextureEffect_PSDualTexture[] = 15, 0, 0, 0, 200, 0, 0, 0, 5, 0, 0, 0, 84, 2, 0, 0, 64, 1, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -127,7 +127,7 @@ const BYTE DualTextureEffect_PSDualTexture[] = 115, 92, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 69, 102, 102, 101, 99, - 116, 46, 102, 120, 0, 67, + 116, 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -141,26 +141,26 @@ const BYTE DualTextureEffect_PSDualTexture[] = 111, 109, 109, 111, 110, 46, 102, 120, 104, 0, 40, 0, 0, 0, 121, 0, 0, 0, - 0, 0, 255, 255, 236, 2, + 0, 0, 255, 255, 248, 2, 0, 0, 0, 0, 255, 255, - 4, 3, 0, 0, 0, 0, - 255, 255, 16, 3, 0, 0, - 0, 0, 255, 255, 28, 3, + 16, 3, 0, 0, 0, 0, + 255, 255, 28, 3, 0, 0, + 0, 0, 255, 255, 40, 3, 0, 0, 0, 0, 255, 255, - 40, 3, 0, 0, 0, 0, - 255, 255, 52, 3, 0, 0, - 98, 0, 0, 0, 64, 3, + 52, 3, 0, 0, 0, 0, + 255, 255, 64, 3, 0, 0, + 98, 0, 0, 0, 76, 3, 0, 0, 98, 0, 0, 0, - 76, 3, 0, 0, 97, 0, - 0, 0, 92, 3, 0, 0, - 101, 0, 0, 0, 108, 3, + 88, 3, 0, 0, 97, 0, + 0, 0, 104, 3, 0, 0, + 101, 0, 0, 0, 120, 3, 0, 0, 101, 0, 0, 0, - 124, 3, 0, 0, 101, 0, - 0, 0, 140, 3, 0, 0, - 20, 0, 1, 0, 156, 3, + 136, 3, 0, 0, 101, 0, + 0, 0, 152, 3, 0, 0, + 20, 0, 1, 0, 168, 3, 0, 0, 20, 0, 1, 0, - 176, 3, 0, 0, 20, 0, - 1, 0, 196, 3, 0, 0, + 188, 3, 0, 0, 20, 0, + 1, 0, 208, 3, 0, 0, 80, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 0, 171, 171, 1, 0, @@ -230,7 +230,9 @@ const BYTE DualTextureEffect_PSDualTexture[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc index 59cac1cf..6141e032 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc @@ -36,7 +36,7 @@ dcl_2d s0 dcl_2d s1 -#line 113 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 113 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mov r0.xy, t1.wzyx texld r0, r0, s1 // ::overlay<0,1,2,3> texld r1, t1, s0 // ::color<0,1,2,3> @@ -69,24 +69,24 @@ ret const BYTE DualTextureEffect_PSDualTextureNoFog[] = { - 68, 88, 66, 67, 247, 98, - 86, 46, 82, 158, 118, 62, - 77, 41, 130, 108, 229, 62, - 221, 37, 1, 0, 0, 0, - 44, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 250, 151, + 31, 166, 221, 116, 168, 146, + 90, 189, 173, 72, 39, 216, + 90, 165, 1, 0, 0, 0, + 56, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 100, 3, 0, 0, 144, 4, - 0, 0, 248, 4, 0, 0, - 65, 111, 110, 57, 44, 3, - 0, 0, 44, 3, 0, 0, - 0, 2, 255, 255, 0, 3, + 112, 3, 0, 0, 156, 4, + 0, 0, 4, 5, 0, 0, + 65, 111, 110, 57, 56, 3, + 0, 0, 56, 3, 0, 0, + 0, 2, 255, 255, 12, 3, 0, 0, 44, 0, 0, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, 44, 0, 2, 0, 36, 0, 0, 0, 44, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, - 255, 255, 254, 255, 145, 0, + 255, 255, 254, 255, 148, 0, 68, 66, 85, 71, 40, 0, 0, 0, 24, 2, 0, 0, 0, 0, 0, 0, 1, 0, @@ -94,7 +94,7 @@ const BYTE DualTextureEffect_PSDualTextureNoFog[] = 12, 0, 0, 0, 128, 0, 0, 0, 4, 0, 0, 0, 200, 1, 0, 0, 224, 0, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -109,22 +109,22 @@ const BYTE DualTextureEffect_PSDualTextureNoFog[] = 101, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 171, 171, 171, 40, 0, 0, 0, - 0, 0, 255, 255, 76, 2, + 0, 0, 255, 255, 88, 2, 0, 0, 0, 0, 255, 255, - 100, 2, 0, 0, 0, 0, - 255, 255, 112, 2, 0, 0, - 0, 0, 255, 255, 124, 2, + 112, 2, 0, 0, 0, 0, + 255, 255, 124, 2, 0, 0, + 0, 0, 255, 255, 136, 2, 0, 0, 0, 0, 255, 255, - 136, 2, 0, 0, 113, 0, - 0, 0, 148, 2, 0, 0, - 113, 0, 0, 0, 160, 2, + 148, 2, 0, 0, 113, 0, + 0, 0, 160, 2, 0, 0, + 113, 0, 0, 0, 172, 2, 0, 0, 112, 0, 0, 0, - 176, 2, 0, 0, 116, 0, - 0, 0, 192, 2, 0, 0, - 116, 0, 0, 0, 208, 2, + 188, 2, 0, 0, 116, 0, + 0, 0, 204, 2, 0, 0, + 116, 0, 0, 0, 220, 2, 0, 0, 116, 0, 0, 0, - 224, 2, 0, 0, 116, 0, - 0, 0, 240, 2, 0, 0, + 236, 2, 0, 0, 116, 0, + 0, 0, 252, 2, 0, 0, 80, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 78, 111, 70, 111, 103, @@ -183,7 +183,9 @@ const BYTE DualTextureEffect_PSDualTextureNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 0, 0, 15, 160, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc index 9c93e422..31eaed44 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc @@ -46,7 +46,7 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSDualTexture<14> #line 14 @@ -59,15 +59,15 @@ dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 33 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 33 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSDualTexture<12,13> mov oPos.w, r0.z // ::VSDualTexture<15> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSDualTexture<0,1,2,3> mov oT1.xyz, c7.x // ::VSDualTexture<4,5,6> -#line 40 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 40 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mov oT2.xy, v1 // ::VSDualTexture<8,9> mov oT2.zw, v2.xyyx // ::VSDualTexture<11,10> @@ -97,17 +97,17 @@ ret const BYTE DualTextureEffect_VSDualTexture[] = { - 68, 88, 66, 67, 77, 60, - 45, 61, 77, 38, 39, 90, - 195, 111, 157, 76, 71, 113, - 130, 199, 1, 0, 0, 0, - 184, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 168, 231, + 169, 97, 141, 233, 232, 127, + 145, 47, 47, 139, 242, 178, + 139, 219, 1, 0, 0, 0, + 196, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 28, 5, 0, 0, 164, 6, - 0, 0, 20, 7, 0, 0, - 65, 111, 110, 57, 228, 4, - 0, 0, 228, 4, 0, 0, - 0, 2, 254, 255, 164, 4, + 40, 5, 0, 0, 176, 6, + 0, 0, 32, 7, 0, 0, + 65, 111, 110, 57, 240, 4, + 0, 0, 240, 4, 0, 0, + 0, 2, 254, 255, 176, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -118,14 +118,14 @@ const BYTE DualTextureEffect_VSDualTexture[] = 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 231, 0, 68, 66, 85, 71, + 234, 0, 68, 66, 85, 71, 40, 0, 0, 0, 112, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 17, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 52, 3, 0, 0, - 80, 1, 0, 0, 67, 58, + 80, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -137,7 +137,7 @@ const BYTE DualTextureEffect_VSDualTexture[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -153,28 +153,28 @@ const BYTE DualTextureEffect_VSDualTexture[] = 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 164, 3, 0, 0, 0, 0, - 255, 255, 188, 3, 0, 0, - 0, 0, 255, 255, 200, 3, + 176, 3, 0, 0, 0, 0, + 255, 255, 200, 3, 0, 0, + 0, 0, 255, 255, 212, 3, 0, 0, 0, 0, 255, 255, - 212, 3, 0, 0, 43, 0, - 0, 0, 224, 3, 0, 0, - 14, 0, 0, 0, 240, 3, + 224, 3, 0, 0, 43, 0, + 0, 0, 236, 3, 0, 0, + 14, 0, 0, 0, 252, 3, 0, 0, 14, 0, 0, 0, - 0, 4, 0, 0, 14, 0, - 0, 0, 16, 4, 0, 0, - 43, 0, 0, 0, 32, 4, + 12, 4, 0, 0, 14, 0, + 0, 0, 28, 4, 0, 0, + 43, 0, 0, 0, 44, 4, 0, 0, 43, 0, 0, 0, - 48, 4, 0, 0, 43, 0, - 0, 0, 64, 4, 0, 0, - 33, 0, 1, 0, 80, 4, + 60, 4, 0, 0, 43, 0, + 0, 0, 76, 4, 0, 0, + 33, 0, 1, 0, 92, 4, 0, 0, 33, 0, 1, 0, - 100, 4, 0, 0, 44, 0, - 0, 0, 112, 4, 0, 0, - 45, 0, 0, 0, 124, 4, + 112, 4, 0, 0, 44, 0, + 0, 0, 124, 4, 0, 0, + 45, 0, 0, 0, 136, 4, 0, 0, 40, 0, 1, 0, - 136, 4, 0, 0, 40, 0, - 1, 0, 148, 4, 0, 0, + 148, 4, 0, 0, 40, 0, + 1, 0, 160, 4, 0, 0, 86, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 0, 68, 105, 102, 102, @@ -272,7 +272,9 @@ const BYTE DualTextureEffect_VSDualTexture[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc index 0e7dc755..7c3e40af 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc @@ -44,20 +44,20 @@ dcl_texcoord1 v1 // vin<4,5> dcl_texcoord2 v2 // vin<6,7> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSDualTextureNoFog<10> dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 48 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 48 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSDualTextureNoFog<8,9> mov oPos.w, r0.z // ::VSDualTextureNoFog<11> -#line 44 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 44 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT0, c1 // ::VSDualTextureNoFog<0,1,2,3> -#line 55 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 55 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mov oT1.xy, v1 // ::VSDualTextureNoFog<4,5> mov oT1.zw, v2.xyyx // ::VSDualTextureNoFog<7,6> @@ -84,17 +84,17 @@ ret const BYTE DualTextureEffect_VSDualTextureNoFog[] = { - 68, 88, 66, 67, 226, 38, - 56, 142, 173, 71, 126, 81, - 49, 0, 70, 146, 32, 177, - 75, 62, 1, 0, 0, 0, - 192, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 166, 141, + 11, 90, 163, 166, 184, 17, + 39, 78, 75, 205, 118, 225, + 189, 206, 1, 0, 0, 0, + 204, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 136, 4, 0, 0, 196, 5, - 0, 0, 52, 6, 0, 0, - 65, 111, 110, 57, 80, 4, - 0, 0, 80, 4, 0, 0, - 0, 2, 254, 255, 16, 4, + 148, 4, 0, 0, 208, 5, + 0, 0, 64, 6, 0, 0, + 65, 111, 110, 57, 92, 4, + 0, 0, 92, 4, 0, 0, + 0, 2, 254, 255, 28, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -105,14 +105,14 @@ const BYTE DualTextureEffect_VSDualTextureNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 215, 0, 68, 66, 85, 71, + 218, 0, 68, 66, 85, 71, 40, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 12, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 244, 2, 0, 0, - 40, 1, 0, 0, 67, 58, + 40, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -124,7 +124,7 @@ const BYTE DualTextureEffect_VSDualTextureNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -140,21 +140,21 @@ const BYTE DualTextureEffect_VSDualTextureNoFog[] = 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 100, 3, 0, 0, 0, 0, - 255, 255, 112, 3, 0, 0, - 0, 0, 255, 255, 124, 3, + 112, 3, 0, 0, 0, 0, + 255, 255, 124, 3, 0, 0, + 0, 0, 255, 255, 136, 3, 0, 0, 43, 0, 0, 0, - 136, 3, 0, 0, 43, 0, - 0, 0, 152, 3, 0, 0, - 43, 0, 0, 0, 168, 3, + 148, 3, 0, 0, 43, 0, + 0, 0, 164, 3, 0, 0, + 43, 0, 0, 0, 180, 3, 0, 0, 43, 0, 0, 0, - 184, 3, 0, 0, 48, 0, - 1, 0, 200, 3, 0, 0, - 48, 0, 1, 0, 220, 3, + 196, 3, 0, 0, 48, 0, + 1, 0, 212, 3, 0, 0, + 48, 0, 1, 0, 232, 3, 0, 0, 44, 0, 0, 0, - 232, 3, 0, 0, 55, 0, - 1, 0, 244, 3, 0, 0, - 55, 0, 1, 0, 0, 4, + 244, 3, 0, 0, 55, 0, + 1, 0, 0, 4, 0, 0, + 55, 0, 1, 0, 12, 4, 0, 0, 86, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 78, 111, 70, @@ -248,7 +248,9 @@ const BYTE DualTextureEffect_VSDualTextureNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc index e325c8e5..81866a7c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc @@ -48,7 +48,7 @@ dcl_texcoord2 v2 // vin<6,7> dcl_texcoord3 v3 // vin<8,9,10,11> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c5 // ::VSDualTextureVc<14> #line 14 @@ -56,22 +56,22 @@ max r0.x, r0.x, c7.x min oT1.w, r0.x, c7.y // ::VSDualTextureVc<7> -#line 72 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 72 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mul oT0, v3, c1 // ::VSDualTextureVc<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c3 // ::vout<0> dp4 r0.y, v0, c4 // ::vout<1> dp4 r0.z, v0, c6 // ::vout<3> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSDualTextureVc<12,13> mov oPos.w, r0.z // ::VSDualTextureVc<15> -#line 45 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 45 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mov oT1.xyz, c7.x // ::VSDualTextureVc<4,5,6> -#line 70 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 70 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mov oT2.xy, v1 // ::VSDualTextureVc<8,9> mov oT2.zw, v2.xyyx // ::VSDualTextureVc<11,10> @@ -102,17 +102,17 @@ ret const BYTE DualTextureEffect_VSDualTextureVc[] = { - 68, 88, 66, 67, 23, 20, - 57, 133, 81, 250, 177, 30, - 147, 64, 150, 199, 71, 109, - 18, 136, 1, 0, 0, 0, - 24, 8, 0, 0, 4, 0, + 68, 88, 66, 67, 106, 148, + 169, 17, 179, 79, 235, 146, + 88, 5, 112, 244, 5, 163, + 192, 80, 1, 0, 0, 0, + 36, 8, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 76, 5, 0, 0, 232, 6, - 0, 0, 116, 7, 0, 0, - 65, 111, 110, 57, 20, 5, - 0, 0, 20, 5, 0, 0, - 0, 2, 254, 255, 212, 4, + 88, 5, 0, 0, 244, 6, + 0, 0, 128, 7, 0, 0, + 65, 111, 110, 57, 32, 5, + 0, 0, 32, 5, 0, 0, + 0, 2, 254, 255, 224, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -123,14 +123,14 @@ const BYTE DualTextureEffect_VSDualTextureVc[] = 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 239, 0, 68, 66, 85, 71, + 242, 0, 68, 66, 85, 71, 40, 0, 0, 0, 144, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 18, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 84, 3, 0, 0, - 88, 1, 0, 0, 67, 58, + 88, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -142,7 +142,7 @@ const BYTE DualTextureEffect_VSDualTextureVc[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -158,29 +158,29 @@ const BYTE DualTextureEffect_VSDualTextureVc[] = 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 196, 3, 0, 0, 0, 0, - 255, 255, 220, 3, 0, 0, - 0, 0, 255, 255, 232, 3, + 208, 3, 0, 0, 0, 0, + 255, 255, 232, 3, 0, 0, + 0, 0, 255, 255, 244, 3, 0, 0, 0, 0, 255, 255, - 244, 3, 0, 0, 0, 0, - 255, 255, 0, 4, 0, 0, - 43, 0, 0, 0, 12, 4, + 0, 4, 0, 0, 0, 0, + 255, 255, 12, 4, 0, 0, + 43, 0, 0, 0, 24, 4, 0, 0, 14, 0, 0, 0, - 28, 4, 0, 0, 14, 0, - 0, 0, 44, 4, 0, 0, - 14, 0, 0, 0, 60, 4, + 40, 4, 0, 0, 14, 0, + 0, 0, 56, 4, 0, 0, + 14, 0, 0, 0, 72, 4, 0, 0, 72, 0, 1, 0, - 76, 4, 0, 0, 43, 0, - 0, 0, 92, 4, 0, 0, - 43, 0, 0, 0, 108, 4, + 88, 4, 0, 0, 43, 0, + 0, 0, 104, 4, 0, 0, + 43, 0, 0, 0, 120, 4, 0, 0, 43, 0, 0, 0, - 124, 4, 0, 0, 63, 0, - 1, 0, 140, 4, 0, 0, - 63, 0, 1, 0, 160, 4, + 136, 4, 0, 0, 63, 0, + 1, 0, 152, 4, 0, 0, + 63, 0, 1, 0, 172, 4, 0, 0, 45, 0, 0, 0, - 172, 4, 0, 0, 70, 0, - 1, 0, 184, 4, 0, 0, - 70, 0, 1, 0, 196, 4, + 184, 4, 0, 0, 70, 0, + 1, 0, 196, 4, 0, 0, + 70, 0, 1, 0, 208, 4, 0, 0, 86, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 86, 99, 0, @@ -282,7 +282,9 @@ const BYTE DualTextureEffect_VSDualTextureVc[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 7, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc index a9ee8399..04774e94 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc @@ -46,18 +46,18 @@ dcl_texcoord2 v2 // vin<6,7> dcl_texcoord3 v3 // vin<8,9,10,11> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 oPos.z, v0, c4 // ::VSDualTextureVcNoFog<10> -#line 88 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 88 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mul oT0, v3, c1 // ::VSDualTextureVcNoFog<0,1,2,3> -#line 43 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 43 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c2 // ::vout<0> dp4 r0.y, v0, c3 // ::vout<1> dp4 r0.z, v0, c5 // ::vout<3> -#line 79 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" +#line 79 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\DualTextureEffect.fx" mad oPos.xy, r0.z, c0, r0 // ::VSDualTextureVcNoFog<8,9> mov oPos.w, r0.z // ::VSDualTextureVcNoFog<11> @@ -89,17 +89,17 @@ ret const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = { - 68, 88, 66, 67, 48, 59, - 151, 148, 181, 214, 129, 185, - 85, 40, 102, 178, 177, 247, - 49, 227, 1, 0, 0, 0, - 36, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 83, 34, + 138, 82, 24, 200, 234, 134, + 143, 249, 9, 117, 84, 240, + 49, 183, 1, 0, 0, 0, + 48, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 188, 4, 0, 0, 12, 6, - 0, 0, 152, 6, 0, 0, - 65, 111, 110, 57, 132, 4, - 0, 0, 132, 4, 0, 0, - 0, 2, 254, 255, 68, 4, + 200, 4, 0, 0, 24, 6, + 0, 0, 164, 6, 0, 0, + 65, 111, 110, 57, 144, 4, + 0, 0, 144, 4, 0, 0, + 0, 2, 254, 255, 80, 4, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, @@ -110,14 +110,14 @@ const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 224, 0, 68, 66, 85, 71, + 227, 0, 68, 66, 85, 71, 40, 0, 0, 0, 84, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 192, 0, 0, 0, 13, 0, 0, 0, 200, 0, 0, 0, 3, 0, 0, 0, 24, 3, 0, 0, - 48, 1, 0, 0, 67, 58, + 48, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -129,7 +129,7 @@ const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 67, 111, 109, 109, 111, 110, 46, 102, - 120, 104, 0, 67, 58, 92, + 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -145,23 +145,23 @@ const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, 111, 0, 0, 0, 0, 0, 255, 255, - 136, 3, 0, 0, 0, 0, - 255, 255, 148, 3, 0, 0, - 0, 0, 255, 255, 160, 3, + 148, 3, 0, 0, 0, 0, + 255, 255, 160, 3, 0, 0, + 0, 0, 255, 255, 172, 3, 0, 0, 0, 0, 255, 255, - 172, 3, 0, 0, 43, 0, - 0, 0, 184, 3, 0, 0, - 88, 0, 1, 0, 200, 3, + 184, 3, 0, 0, 43, 0, + 0, 0, 196, 3, 0, 0, + 88, 0, 1, 0, 212, 3, 0, 0, 43, 0, 0, 0, - 216, 3, 0, 0, 43, 0, - 0, 0, 232, 3, 0, 0, - 43, 0, 0, 0, 248, 3, + 228, 3, 0, 0, 43, 0, + 0, 0, 244, 3, 0, 0, + 43, 0, 0, 0, 4, 4, 0, 0, 79, 0, 1, 0, - 8, 4, 0, 0, 79, 0, - 1, 0, 28, 4, 0, 0, - 86, 0, 1, 0, 40, 4, + 20, 4, 0, 0, 79, 0, + 1, 0, 40, 4, 0, 0, + 86, 0, 1, 0, 52, 4, 0, 0, 86, 0, 1, 0, - 52, 4, 0, 0, 86, 83, + 64, 4, 0, 0, 86, 83, 68, 117, 97, 108, 84, 101, 120, 116, 117, 114, 101, 86, 99, 78, 111, 70, 111, 103, @@ -259,7 +259,9 @@ const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc index 5ae2b1da..58f0fa09 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc @@ -45,7 +45,7 @@ dcl_2d s0 dcl_cube s1 -#line 119 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 119 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" texld r0, t3, s1 texld r1, t2, s0 mul r1, r1, t0 // ::color<0,1,2,3> @@ -54,7 +54,7 @@ mad r0.xyz, r0, r1.w, -r1 mad r0.xyz, t1, r0, r1 // ::color<0,1,2> -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r2.xyz, c0, r1.w, -r0 mad r1.xyz, t1.w, r2, r0 // ApplyFog::color<0,1,2> mov oC0, r1 // ::PSEnvMap<0,1,2,3> @@ -86,17 +86,17 @@ ret const BYTE EnvironmentMapEffect_PSEnvMap[] = { - 68, 88, 66, 67, 249, 64, - 205, 226, 17, 105, 132, 168, - 201, 219, 42, 31, 200, 38, - 157, 247, 1, 0, 0, 0, - 136, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 177, 158, + 75, 63, 79, 76, 68, 211, + 60, 87, 84, 236, 162, 23, + 139, 200, 1, 0, 0, 0, + 148, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 32, 4, 0, 0, 212, 5, - 0, 0, 84, 6, 0, 0, - 65, 111, 110, 57, 232, 3, - 0, 0, 232, 3, 0, 0, - 0, 2, 255, 255, 176, 3, + 44, 4, 0, 0, 224, 5, + 0, 0, 96, 6, 0, 0, + 65, 111, 110, 57, 244, 3, + 0, 0, 244, 3, 0, 0, + 0, 2, 255, 255, 188, 3, 0, 0, 56, 0, 0, 0, 1, 0, 44, 0, 0, 0, 56, 0, 0, 0, 56, 0, @@ -105,7 +105,7 @@ const BYTE EnvironmentMapEffect_PSEnvMap[] = 1, 1, 1, 0, 0, 0, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 255, 255, 254, 255, 180, 0, + 255, 255, 254, 255, 183, 0, 68, 66, 85, 71, 40, 0, 0, 0, 164, 2, 0, 0, 0, 0, 0, 0, 2, 0, @@ -113,7 +113,7 @@ const BYTE EnvironmentMapEffect_PSEnvMap[] = 14, 0, 0, 0, 204, 0, 0, 0, 4, 0, 0, 0, 84, 2, 0, 0, 60, 1, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -127,7 +127,7 @@ const BYTE EnvironmentMapEffect_PSEnvMap[] = 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, 46, 102, - 120, 0, 67, 58, 92, 65, + 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -141,24 +141,24 @@ const BYTE EnvironmentMapEffect_PSEnvMap[] = 111, 110, 46, 102, 120, 104, 0, 171, 40, 0, 0, 0, 124, 0, 0, 0, 0, 0, - 255, 255, 216, 2, 0, 0, - 0, 0, 255, 255, 228, 2, + 255, 255, 228, 2, 0, 0, + 0, 0, 255, 255, 240, 2, 0, 0, 0, 0, 255, 255, - 240, 2, 0, 0, 0, 0, - 255, 255, 252, 2, 0, 0, - 0, 0, 255, 255, 8, 3, + 252, 2, 0, 0, 0, 0, + 255, 255, 8, 3, 0, 0, + 0, 0, 255, 255, 20, 3, 0, 0, 0, 0, 255, 255, - 20, 3, 0, 0, 119, 0, - 0, 0, 32, 3, 0, 0, - 118, 0, 0, 0, 48, 3, + 32, 3, 0, 0, 119, 0, + 0, 0, 44, 3, 0, 0, + 118, 0, 0, 0, 60, 3, 0, 0, 118, 0, 0, 0, - 64, 3, 0, 0, 121, 0, - 0, 0, 80, 3, 0, 0, - 121, 0, 0, 0, 100, 3, + 76, 3, 0, 0, 121, 0, + 0, 0, 92, 3, 0, 0, + 121, 0, 0, 0, 112, 3, 0, 0, 20, 0, 1, 0, - 120, 3, 0, 0, 20, 0, - 1, 0, 140, 3, 0, 0, - 20, 0, 1, 0, 160, 3, + 132, 3, 0, 0, 20, 0, + 1, 0, 152, 3, 0, 0, + 20, 0, 1, 0, 172, 3, 0, 0, 80, 83, 69, 110, 118, 77, 97, 112, 0, 171, 171, 171, 1, 0, 3, 0, @@ -225,7 +225,9 @@ const BYTE EnvironmentMapEffect_PSEnvMap[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc index eb694541..10125849 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc @@ -38,7 +38,7 @@ dcl_2d s0 dcl_cube s1 -#line 133 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 133 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" texld r0, t3, s1 texld r1, t2, s0 mul r1, r1, t0 // ::color<0,1,2,3> @@ -72,24 +72,24 @@ ret const BYTE EnvironmentMapEffect_PSEnvMapNoFog[] = { - 68, 88, 66, 67, 78, 221, - 166, 19, 205, 36, 156, 195, - 209, 43, 31, 5, 92, 24, - 27, 50, 1, 0, 0, 0, - 116, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 58, 42, + 65, 245, 188, 132, 226, 215, + 14, 184, 178, 36, 242, 162, + 41, 157, 1, 0, 0, 0, + 128, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 108, 3, 0, 0, 192, 4, - 0, 0, 64, 5, 0, 0, - 65, 111, 110, 57, 52, 3, - 0, 0, 52, 3, 0, 0, - 0, 2, 255, 255, 8, 3, + 120, 3, 0, 0, 204, 4, + 0, 0, 76, 5, 0, 0, + 65, 111, 110, 57, 64, 3, + 0, 0, 64, 3, 0, 0, + 0, 2, 255, 255, 20, 3, 0, 0, 44, 0, 0, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, 44, 0, 2, 0, 36, 0, 0, 0, 44, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, - 255, 255, 254, 255, 148, 0, + 255, 255, 254, 255, 151, 0, 68, 66, 85, 71, 40, 0, 0, 0, 36, 2, 0, 0, 0, 0, 0, 0, 1, 0, @@ -97,7 +97,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapNoFog[] = 12, 0, 0, 0, 128, 0, 0, 0, 3, 0, 0, 0, 232, 1, 0, 0, 224, 0, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -112,22 +112,22 @@ const BYTE EnvironmentMapEffect_PSEnvMapNoFog[] = 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, - 0, 0, 255, 255, 88, 2, + 0, 0, 255, 255, 100, 2, 0, 0, 0, 0, 255, 255, - 100, 2, 0, 0, 0, 0, - 255, 255, 112, 2, 0, 0, - 0, 0, 255, 255, 124, 2, + 112, 2, 0, 0, 0, 0, + 255, 255, 124, 2, 0, 0, + 0, 0, 255, 255, 136, 2, 0, 0, 0, 0, 255, 255, - 136, 2, 0, 0, 0, 0, - 255, 255, 148, 2, 0, 0, - 133, 0, 0, 0, 160, 2, + 148, 2, 0, 0, 0, 0, + 255, 255, 160, 2, 0, 0, + 133, 0, 0, 0, 172, 2, 0, 0, 132, 0, 0, 0, - 176, 2, 0, 0, 132, 0, - 0, 0, 192, 2, 0, 0, - 135, 0, 0, 0, 208, 2, + 188, 2, 0, 0, 132, 0, + 0, 0, 204, 2, 0, 0, + 135, 0, 0, 0, 220, 2, 0, 0, 135, 0, 0, 0, - 228, 2, 0, 0, 135, 0, - 0, 0, 248, 2, 0, 0, + 240, 2, 0, 0, 135, 0, + 0, 0, 4, 3, 0, 0, 80, 83, 69, 110, 118, 77, 97, 112, 78, 111, 70, 111, 103, 0, 171, 171, 1, 0, @@ -188,7 +188,9 @@ const BYTE EnvironmentMapEffect_PSEnvMapNoFog[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc index 3403f7a2..10a67838 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc @@ -46,7 +46,7 @@ dcl_2d s0 dcl_cube s1 -#line 145 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 145 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" texld r0, t3, s1 texld r1, t2, s0 mul r1, r1, t0 // ::color<0,1,2,3> @@ -57,7 +57,7 @@ mad r0.xyz, t1, r0, r1 // ::color<0,1,2> mad r0.xyz, c0, r0.w, r0 // ::color<0,1,2> -#line 20 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 20 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r2.xyz, c1, r1.w, -r0 mad r1.xyz, t1.w, r2, r0 // ApplyFog::color<0,1,2> mov oC0, r1 // ::PSEnvMapSpecular<0,1,2,3> @@ -91,17 +91,17 @@ ret const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = { - 68, 88, 66, 67, 42, 23, - 166, 79, 167, 173, 59, 45, - 21, 59, 137, 29, 86, 104, - 179, 112, 1, 0, 0, 0, - 72, 7, 0, 0, 4, 0, + 68, 88, 66, 67, 153, 70, + 64, 29, 2, 230, 217, 33, + 179, 118, 80, 7, 144, 187, + 164, 92, 1, 0, 0, 0, + 84, 7, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 156, 4, 0, 0, 148, 6, - 0, 0, 20, 7, 0, 0, - 65, 111, 110, 57, 100, 4, - 0, 0, 100, 4, 0, 0, - 0, 2, 255, 255, 32, 4, + 168, 4, 0, 0, 160, 6, + 0, 0, 32, 7, 0, 0, + 65, 111, 110, 57, 112, 4, + 0, 0, 112, 4, 0, 0, + 0, 2, 255, 255, 44, 4, 0, 0, 68, 0, 0, 0, 2, 0, 44, 0, 0, 0, 68, 0, 0, 0, 68, 0, @@ -112,7 +112,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = 0, 0, 0, 0, 0, 0, 11, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, - 255, 255, 254, 255, 199, 0, + 255, 255, 254, 255, 202, 0, 68, 66, 85, 71, 40, 0, 0, 0, 240, 2, 0, 0, 0, 0, 0, 0, 2, 0, @@ -120,7 +120,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = 16, 0, 0, 0, 204, 0, 0, 0, 5, 0, 0, 0, 140, 2, 0, 0, 76, 1, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -134,7 +134,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, 46, 102, - 120, 0, 67, 58, 92, 65, + 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -148,27 +148,27 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = 111, 110, 46, 102, 120, 104, 0, 171, 40, 0, 0, 0, 124, 0, 0, 0, 0, 0, - 255, 255, 36, 3, 0, 0, - 0, 0, 255, 255, 48, 3, + 255, 255, 48, 3, 0, 0, + 0, 0, 255, 255, 60, 3, 0, 0, 0, 0, 255, 255, - 60, 3, 0, 0, 0, 0, - 255, 255, 72, 3, 0, 0, - 0, 0, 255, 255, 84, 3, + 72, 3, 0, 0, 0, 0, + 255, 255, 84, 3, 0, 0, + 0, 0, 255, 255, 96, 3, 0, 0, 0, 0, 255, 255, - 96, 3, 0, 0, 145, 0, - 0, 0, 108, 3, 0, 0, - 144, 0, 0, 0, 124, 3, + 108, 3, 0, 0, 145, 0, + 0, 0, 120, 3, 0, 0, + 144, 0, 0, 0, 136, 3, 0, 0, 144, 0, 0, 0, - 140, 3, 0, 0, 147, 0, - 0, 0, 156, 3, 0, 0, - 145, 0, 0, 0, 176, 3, + 152, 3, 0, 0, 147, 0, + 0, 0, 168, 3, 0, 0, + 145, 0, 0, 0, 188, 3, 0, 0, 147, 0, 0, 0, - 192, 3, 0, 0, 148, 0, - 0, 0, 212, 3, 0, 0, - 20, 0, 1, 0, 232, 3, + 204, 3, 0, 0, 148, 0, + 0, 0, 224, 3, 0, 0, + 20, 0, 1, 0, 244, 3, 0, 0, 20, 0, 1, 0, - 252, 3, 0, 0, 20, 0, - 1, 0, 16, 4, 0, 0, + 8, 4, 0, 0, 20, 0, + 1, 0, 28, 4, 0, 0, 80, 83, 69, 110, 118, 77, 97, 112, 83, 112, 101, 99, 117, 108, 97, 114, 0, 171, @@ -245,7 +245,9 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 31, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc index 3fe78386..b4b0e425 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc @@ -45,7 +45,7 @@ dcl_2d s0 dcl_cube s1 -#line 160 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 160 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" texld r0, t3, s1 texld r1, t2, s0 mul r1, r1, t0 // ::color<0,1,2,3> @@ -84,17 +84,17 @@ ret const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = { - 68, 88, 66, 67, 200, 148, - 20, 147, 120, 122, 183, 154, - 225, 8, 208, 18, 28, 171, - 65, 163, 1, 0, 0, 0, - 68, 6, 0, 0, 4, 0, + 68, 88, 66, 67, 139, 134, + 181, 113, 33, 141, 211, 99, + 191, 226, 235, 126, 77, 74, + 49, 187, 1, 0, 0, 0, + 80, 6, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 232, 3, 0, 0, 144, 5, - 0, 0, 16, 6, 0, 0, - 65, 111, 110, 57, 176, 3, - 0, 0, 176, 3, 0, 0, - 0, 2, 255, 255, 120, 3, + 244, 3, 0, 0, 156, 5, + 0, 0, 28, 6, 0, 0, + 65, 111, 110, 57, 188, 3, + 0, 0, 188, 3, 0, 0, + 0, 2, 255, 255, 132, 3, 0, 0, 56, 0, 0, 0, 1, 0, 44, 0, 0, 0, 56, 0, 0, 0, 56, 0, @@ -103,7 +103,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 255, 255, 254, 255, 167, 0, + 255, 255, 254, 255, 170, 0, 68, 66, 85, 71, 40, 0, 0, 0, 112, 2, 0, 0, 0, 0, 0, 0, 1, 0, @@ -111,7 +111,7 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = 14, 0, 0, 0, 128, 0, 0, 0, 4, 0, 0, 0, 32, 2, 0, 0, 240, 0, - 0, 0, 67, 58, 92, 65, + 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, 109, @@ -126,25 +126,25 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, - 0, 0, 255, 255, 164, 2, + 0, 0, 255, 255, 176, 2, 0, 0, 0, 0, 255, 255, - 176, 2, 0, 0, 0, 0, - 255, 255, 188, 2, 0, 0, - 0, 0, 255, 255, 200, 2, + 188, 2, 0, 0, 0, 0, + 255, 255, 200, 2, 0, 0, + 0, 0, 255, 255, 212, 2, 0, 0, 0, 0, 255, 255, - 212, 2, 0, 0, 0, 0, - 255, 255, 224, 2, 0, 0, - 160, 0, 0, 0, 236, 2, + 224, 2, 0, 0, 0, 0, + 255, 255, 236, 2, 0, 0, + 160, 0, 0, 0, 248, 2, 0, 0, 159, 0, 0, 0, - 252, 2, 0, 0, 159, 0, - 0, 0, 12, 3, 0, 0, - 162, 0, 0, 0, 28, 3, + 8, 3, 0, 0, 159, 0, + 0, 0, 24, 3, 0, 0, + 162, 0, 0, 0, 40, 3, 0, 0, 160, 0, 0, 0, - 48, 3, 0, 0, 162, 0, - 0, 0, 64, 3, 0, 0, - 163, 0, 0, 0, 84, 3, + 60, 3, 0, 0, 162, 0, + 0, 0, 76, 3, 0, 0, + 163, 0, 0, 0, 96, 3, 0, 0, 163, 0, 0, 0, - 104, 3, 0, 0, 80, 83, + 116, 3, 0, 0, 80, 83, 69, 110, 118, 77, 97, 112, 83, 112, 101, 99, 117, 108, 97, 114, 78, 111, 70, 111, @@ -215,7 +215,9 @@ const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc index 09c6b034..4e62d0ad 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc @@ -47,13 +47,13 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 67 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 67 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, v1, c15 dp3 r0.y, v1, c16 dp3 r0.z, v1, c17 nrm r1.xyz, r0 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, -c4, r1 // ::dotL<0> dp3 r0.y, -c5, r1 // ::dotL<1> dp3 r0.z, -c6, r1 // ::dotL<2> @@ -69,15 +69,15 @@ mov r2.xyz, c2 // Parameters::DiffuseColor<0,1,2> mad oT0.xyz, r0, r2, c3 // ::VSEnvMap<0,1,2> -#line 71 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 71 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 oPos.z, v0, c20 // ::VSEnvMap<15> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c11 max r0.x, r0.x, c22.x min oT1.w, r0.x, c22.y // ::VSEnvMap<7> -#line 65 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 65 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 r0.x, v0, c12 // ::pos_ws<0> dp4 r0.y, v0, c13 // ::pos_ws<1> dp4 r0.z, v0, c14 // ::pos_ws<2> @@ -98,10 +98,10 @@ mad oPos.xy, r0.z, c0, r0 // ::VSEnvMap<13,14> mov oPos.w, r0.z // ::VSEnvMap<16> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c2.w // ::VSEnvMap<3> -#line 77 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 77 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" mov oT1.xyz, c1.x // ::VSEnvMap<4,5,6> #line 90 @@ -159,17 +159,17 @@ ret const BYTE EnvironmentMapEffect_VSEnvMap[] = { - 68, 88, 66, 67, 101, 124, - 44, 126, 5, 169, 99, 18, - 224, 136, 152, 151, 55, 62, - 154, 235, 1, 0, 0, 0, - 152, 14, 0, 0, 4, 0, + 68, 88, 66, 67, 19, 121, + 10, 102, 94, 99, 77, 158, + 27, 223, 218, 240, 76, 135, + 126, 227, 1, 0, 0, 0, + 164, 14, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 180, 8, 0, 0, 128, 13, - 0, 0, 244, 13, 0, 0, - 65, 111, 110, 57, 124, 8, - 0, 0, 124, 8, 0, 0, - 0, 2, 254, 255, 48, 8, + 192, 8, 0, 0, 140, 13, + 0, 0, 0, 14, 0, 0, + 65, 111, 110, 57, 136, 8, + 0, 0, 136, 8, 0, 0, + 0, 2, 254, 255, 60, 8, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -182,14 +182,14 @@ const BYTE EnvironmentMapEffect_VSEnvMap[] = 7, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 116, 1, 68, 66, 85, 71, + 119, 1, 68, 66, 85, 71, 40, 0, 0, 0, 164, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 1, 0, 0, 38, 0, 0, 0, 24, 1, 0, 0, 10, 0, 0, 0, 220, 4, 0, 0, - 124, 2, 0, 0, 67, 58, + 124, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -203,7 +203,7 @@ const BYTE EnvironmentMapEffect_VSEnvMap[] = 118, 105, 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, - 46, 102, 120, 0, 67, 58, + 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -215,7 +215,7 @@ const BYTE EnvironmentMapEffect_VSEnvMap[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -230,56 +230,56 @@ const BYTE EnvironmentMapEffect_VSEnvMap[] = 102, 120, 104, 0, 40, 0, 0, 0, 124, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 255, 255, 216, 5, 0, 0, - 0, 0, 255, 255, 240, 5, + 255, 255, 228, 5, 0, 0, + 0, 0, 255, 255, 252, 5, 0, 0, 0, 0, 255, 255, - 252, 5, 0, 0, 0, 0, - 255, 255, 8, 6, 0, 0, - 67, 0, 0, 0, 20, 6, + 8, 6, 0, 0, 0, 0, + 255, 255, 20, 6, 0, 0, + 67, 0, 0, 0, 32, 6, 0, 0, 67, 0, 0, 0, - 36, 6, 0, 0, 67, 0, - 0, 0, 52, 6, 0, 0, - 67, 0, 0, 0, 68, 6, + 48, 6, 0, 0, 67, 0, + 0, 0, 64, 6, 0, 0, + 67, 0, 0, 0, 80, 6, 0, 0, 36, 0, 1, 0, - 80, 6, 0, 0, 36, 0, - 1, 0, 96, 6, 0, 0, - 36, 0, 1, 0, 112, 6, + 92, 6, 0, 0, 36, 0, + 1, 0, 108, 6, 0, 0, + 36, 0, 1, 0, 124, 6, 0, 0, 39, 0, 1, 0, - 128, 6, 0, 0, 41, 0, - 1, 0, 144, 6, 0, 0, - 46, 0, 1, 0, 160, 6, + 140, 6, 0, 0, 41, 0, + 1, 0, 156, 6, 0, 0, + 46, 0, 1, 0, 172, 6, 0, 0, 46, 0, 1, 0, - 176, 6, 0, 0, 46, 0, - 1, 0, 196, 6, 0, 0, - 46, 0, 1, 0, 216, 6, + 188, 6, 0, 0, 46, 0, + 1, 0, 208, 6, 0, 0, + 46, 0, 1, 0, 228, 6, 0, 0, 46, 0, 1, 0, - 228, 6, 0, 0, 71, 0, - 0, 0, 248, 6, 0, 0, - 14, 0, 2, 0, 8, 7, + 240, 6, 0, 0, 71, 0, + 0, 0, 4, 7, 0, 0, + 14, 0, 2, 0, 20, 7, 0, 0, 14, 0, 2, 0, - 24, 7, 0, 0, 14, 0, - 2, 0, 40, 7, 0, 0, - 65, 0, 0, 0, 56, 7, + 36, 7, 0, 0, 14, 0, + 2, 0, 52, 7, 0, 0, + 65, 0, 0, 0, 68, 7, 0, 0, 65, 0, 0, 0, - 72, 7, 0, 0, 65, 0, - 0, 0, 88, 7, 0, 0, - 66, 0, 0, 0, 104, 7, + 84, 7, 0, 0, 65, 0, + 0, 0, 100, 7, 0, 0, + 66, 0, 0, 0, 116, 7, 0, 0, 66, 0, 0, 0, - 120, 7, 0, 0, 81, 0, - 0, 0, 132, 7, 0, 0, - 81, 0, 0, 0, 148, 7, + 132, 7, 0, 0, 81, 0, + 0, 0, 144, 7, 0, 0, + 81, 0, 0, 0, 160, 7, 0, 0, 81, 0, 0, 0, - 164, 7, 0, 0, 71, 0, - 0, 0, 184, 7, 0, 0, - 71, 0, 0, 0, 200, 7, + 176, 7, 0, 0, 71, 0, + 0, 0, 196, 7, 0, 0, + 71, 0, 0, 0, 212, 7, 0, 0, 71, 0, 0, 0, - 216, 7, 0, 0, 88, 0, - 0, 0, 232, 7, 0, 0, - 88, 0, 0, 0, 252, 7, + 228, 7, 0, 0, 88, 0, + 0, 0, 244, 7, 0, 0, + 88, 0, 0, 0, 8, 8, 0, 0, 46, 0, 1, 0, - 8, 8, 0, 0, 77, 0, - 0, 0, 20, 8, 0, 0, - 90, 0, 0, 0, 32, 8, + 20, 8, 0, 0, 77, 0, + 0, 0, 32, 8, 0, 0, + 90, 0, 0, 0, 44, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -430,7 +430,9 @@ const BYTE EnvironmentMapEffect_VSEnvMap[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 22, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc index 9aeb1aa3..3a098c47 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc @@ -47,13 +47,13 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 67 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 67 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, v1, c15 dp3 r0.y, v1, c16 dp3 r0.z, v1, c17 nrm r1.xyz, r0 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, -c4, r1 // ::dotL<0> dp3 r0.y, -c5, r1 // ::dotL<1> dp3 r0.z, -c6, r1 // ::dotL<2> @@ -69,7 +69,7 @@ mov r2.xyz, c2 // Parameters::DiffuseColor<0,1,2> mad oT0.xyz, r0, r2, c3 // ::VSEnvMapFresnel<0,1,2> -#line 71 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 71 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 oPos.z, v0, c20 // ::VSEnvMapFresnel<15> #line 65 @@ -87,12 +87,12 @@ pow r1.w, r0.x, c1.y mul oT1.xyz, r1.w, c1.x // ::VSEnvMapFresnel<4,5,6> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c11 max r0.x, r0.x, c22.x min oT1.w, r0.x, c22.y // ::VSEnvMapFresnel<7> -#line 81 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 81 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, -r2, r1 add r0.x, r0.x, r0.x mad oT3.xyz, r1, -r0.x, -r2 // ::VSEnvMapFresnel<10,11,12> @@ -106,10 +106,10 @@ mad oPos.xy, r0.z, c0, r0 // ::VSEnvMapFresnel<13,14> mov oPos.w, r0.z // ::VSEnvMapFresnel<16> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c2.w // ::VSEnvMapFresnel<3> -#line 97 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 97 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" mov oT2.xy, v2 // ::VSEnvMapFresnel<8,9> // approximately 45 instruction slots used @@ -170,17 +170,17 @@ ret const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = { - 68, 88, 66, 67, 43, 68, - 199, 144, 184, 216, 16, 13, - 30, 112, 195, 220, 61, 145, - 135, 163, 1, 0, 0, 0, - 248, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 253, 9, + 198, 68, 184, 146, 237, 51, + 12, 158, 144, 224, 197, 229, + 123, 5, 1, 0, 0, 0, + 4, 16, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 108, 9, 0, 0, 224, 14, - 0, 0, 84, 15, 0, 0, - 65, 111, 110, 57, 52, 9, - 0, 0, 52, 9, 0, 0, - 0, 2, 254, 255, 232, 8, + 120, 9, 0, 0, 236, 14, + 0, 0, 96, 15, 0, 0, + 65, 111, 110, 57, 64, 9, + 0, 0, 64, 9, 0, 0, + 0, 2, 254, 255, 244, 8, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, @@ -193,14 +193,14 @@ const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = 7, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 142, 1, 68, 66, 85, 71, + 145, 1, 68, 66, 85, 71, 40, 0, 0, 0, 12, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 1, 0, 0, 43, 0, 0, 0, 24, 1, 0, 0, 11, 0, 0, 0, 48, 5, 0, 0, - 164, 2, 0, 0, 67, 58, + 164, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -214,7 +214,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = 118, 105, 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, - 46, 102, 120, 0, 67, 58, + 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -226,7 +226,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -241,63 +241,63 @@ const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = 102, 120, 104, 0, 40, 0, 0, 0, 124, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 255, 255, 64, 6, 0, 0, - 0, 0, 255, 255, 88, 6, + 255, 255, 76, 6, 0, 0, + 0, 0, 255, 255, 100, 6, 0, 0, 0, 0, 255, 255, - 100, 6, 0, 0, 0, 0, - 255, 255, 112, 6, 0, 0, - 67, 0, 0, 0, 124, 6, + 112, 6, 0, 0, 0, 0, + 255, 255, 124, 6, 0, 0, + 67, 0, 0, 0, 136, 6, 0, 0, 67, 0, 0, 0, - 140, 6, 0, 0, 67, 0, - 0, 0, 156, 6, 0, 0, - 67, 0, 0, 0, 172, 6, + 152, 6, 0, 0, 67, 0, + 0, 0, 168, 6, 0, 0, + 67, 0, 0, 0, 184, 6, 0, 0, 36, 0, 1, 0, - 184, 6, 0, 0, 36, 0, - 1, 0, 200, 6, 0, 0, - 36, 0, 1, 0, 216, 6, + 196, 6, 0, 0, 36, 0, + 1, 0, 212, 6, 0, 0, + 36, 0, 1, 0, 228, 6, 0, 0, 39, 0, 1, 0, - 232, 6, 0, 0, 41, 0, - 1, 0, 248, 6, 0, 0, - 46, 0, 1, 0, 8, 7, + 244, 6, 0, 0, 41, 0, + 1, 0, 4, 7, 0, 0, + 46, 0, 1, 0, 20, 7, 0, 0, 46, 0, 1, 0, - 24, 7, 0, 0, 46, 0, - 1, 0, 44, 7, 0, 0, - 46, 0, 1, 0, 64, 7, + 36, 7, 0, 0, 46, 0, + 1, 0, 56, 7, 0, 0, + 46, 0, 1, 0, 76, 7, 0, 0, 46, 0, 1, 0, - 76, 7, 0, 0, 71, 0, - 0, 0, 96, 7, 0, 0, - 65, 0, 0, 0, 112, 7, + 88, 7, 0, 0, 71, 0, + 0, 0, 108, 7, 0, 0, + 65, 0, 0, 0, 124, 7, 0, 0, 65, 0, 0, 0, - 128, 7, 0, 0, 65, 0, - 0, 0, 144, 7, 0, 0, - 66, 0, 0, 0, 160, 7, + 140, 7, 0, 0, 65, 0, + 0, 0, 156, 7, 0, 0, + 66, 0, 0, 0, 172, 7, 0, 0, 66, 0, 0, 0, - 176, 7, 0, 0, 55, 0, - 0, 0, 188, 7, 0, 0, - 57, 0, 0, 0, 204, 7, + 188, 7, 0, 0, 55, 0, + 0, 0, 200, 7, 0, 0, + 57, 0, 0, 0, 216, 7, 0, 0, 57, 0, 0, 0, - 216, 7, 0, 0, 57, 0, - 0, 0, 232, 7, 0, 0, - 57, 0, 0, 0, 248, 7, + 228, 7, 0, 0, 57, 0, + 0, 0, 244, 7, 0, 0, + 57, 0, 0, 0, 4, 8, 0, 0, 57, 0, 0, 0, - 8, 8, 0, 0, 14, 0, - 2, 0, 24, 8, 0, 0, - 14, 0, 2, 0, 40, 8, + 20, 8, 0, 0, 14, 0, + 2, 0, 36, 8, 0, 0, + 14, 0, 2, 0, 52, 8, 0, 0, 14, 0, 2, 0, - 56, 8, 0, 0, 81, 0, - 0, 0, 72, 8, 0, 0, - 81, 0, 0, 0, 88, 8, + 68, 8, 0, 0, 81, 0, + 0, 0, 84, 8, 0, 0, + 81, 0, 0, 0, 100, 8, 0, 0, 81, 0, 0, 0, - 104, 8, 0, 0, 71, 0, - 0, 0, 124, 8, 0, 0, - 71, 0, 0, 0, 140, 8, + 116, 8, 0, 0, 71, 0, + 0, 0, 136, 8, 0, 0, + 71, 0, 0, 0, 152, 8, 0, 0, 71, 0, 0, 0, - 156, 8, 0, 0, 95, 0, - 0, 0, 172, 8, 0, 0, - 95, 0, 0, 0, 192, 8, + 168, 8, 0, 0, 95, 0, + 0, 0, 184, 8, 0, 0, + 95, 0, 0, 0, 204, 8, 0, 0, 46, 0, 1, 0, - 204, 8, 0, 0, 97, 0, - 0, 0, 216, 8, 0, 0, + 216, 8, 0, 0, 97, 0, + 0, 0, 228, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -458,7 +458,9 @@ const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 22, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc index c151c32c..4f719200 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc @@ -49,13 +49,13 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 67 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 67 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, v1, c11 dp3 r0.y, v1, c12 dp3 r0.z, v1, c13 nrm r1.xyz, r0 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, -c4, r1 // ::dotL<0> #line 39 @@ -67,15 +67,15 @@ mov r2.xyz, c2 // Parameters::DiffuseColor<0,1,2> mad oT0.xyz, r0, r2, c3 // ::VSEnvMapOneLight<0,1,2> -#line 71 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 71 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 oPos.z, v0, c16 // ::VSEnvMapOneLight<15> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c7 max r0.x, r0.x, c18.x min oT1.w, r0.x, c18.y // ::VSEnvMapOneLight<7> -#line 65 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 65 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 r0.x, v0, c8 // ::pos_ws<0> dp4 r0.y, v0, c9 // ::pos_ws<1> dp4 r0.z, v0, c10 // ::pos_ws<2> @@ -96,10 +96,10 @@ mad oPos.xy, r0.z, c0, r0 // ::VSEnvMapOneLight<13,14> mov oPos.w, r0.z // ::VSEnvMapOneLight<16> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c2.w // ::VSEnvMapOneLight<3> -#line 77 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 77 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" mov oT1.xyz, c1.x // ::VSEnvMapOneLight<4,5,6> #line 104 @@ -153,17 +153,17 @@ ret const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = { - 68, 88, 66, 67, 47, 235, - 109, 205, 132, 61, 37, 148, - 58, 201, 166, 220, 219, 218, - 33, 237, 1, 0, 0, 0, - 136, 13, 0, 0, 4, 0, + 68, 88, 66, 67, 239, 158, + 103, 125, 117, 198, 247, 206, + 224, 147, 46, 147, 50, 147, + 61, 168, 1, 0, 0, 0, + 148, 13, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 84, 8, 0, 0, 112, 12, - 0, 0, 228, 12, 0, 0, - 65, 111, 110, 57, 28, 8, - 0, 0, 28, 8, 0, 0, - 0, 2, 254, 255, 184, 7, + 96, 8, 0, 0, 124, 12, + 0, 0, 240, 12, 0, 0, + 65, 111, 110, 57, 40, 8, + 0, 0, 40, 8, 0, 0, + 0, 2, 254, 255, 196, 7, 0, 0, 100, 0, 0, 0, 5, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, @@ -180,14 +180,14 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = 7, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 104, 1, 68, 66, 85, 71, + 107, 1, 68, 66, 85, 71, 40, 0, 0, 0, 116, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 1, 0, 0, 34, 0, 0, 0, 24, 1, 0, 0, 10, 0, 0, 0, 172, 4, 0, 0, - 92, 2, 0, 0, 67, 58, + 92, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -201,7 +201,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = 118, 105, 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, - 46, 102, 120, 0, 67, 58, + 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -213,7 +213,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -228,51 +228,51 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = 102, 120, 104, 0, 40, 0, 0, 0, 124, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 255, 255, 168, 5, 0, 0, - 0, 0, 255, 255, 192, 5, + 255, 255, 180, 5, 0, 0, + 0, 0, 255, 255, 204, 5, 0, 0, 0, 0, 255, 255, - 204, 5, 0, 0, 0, 0, - 255, 255, 216, 5, 0, 0, - 67, 0, 0, 0, 228, 5, + 216, 5, 0, 0, 0, 0, + 255, 255, 228, 5, 0, 0, + 67, 0, 0, 0, 240, 5, 0, 0, 67, 0, 0, 0, - 244, 5, 0, 0, 67, 0, - 0, 0, 4, 6, 0, 0, - 67, 0, 0, 0, 20, 6, + 0, 6, 0, 0, 67, 0, + 0, 0, 16, 6, 0, 0, + 67, 0, 0, 0, 32, 6, 0, 0, 36, 0, 1, 0, - 32, 6, 0, 0, 39, 0, - 1, 0, 48, 6, 0, 0, - 41, 0, 1, 0, 64, 6, + 44, 6, 0, 0, 39, 0, + 1, 0, 60, 6, 0, 0, + 41, 0, 1, 0, 76, 6, 0, 0, 46, 0, 1, 0, - 80, 6, 0, 0, 46, 0, - 1, 0, 96, 6, 0, 0, - 46, 0, 1, 0, 108, 6, + 92, 6, 0, 0, 46, 0, + 1, 0, 108, 6, 0, 0, + 46, 0, 1, 0, 120, 6, 0, 0, 71, 0, 0, 0, - 128, 6, 0, 0, 14, 0, - 2, 0, 144, 6, 0, 0, - 14, 0, 2, 0, 160, 6, + 140, 6, 0, 0, 14, 0, + 2, 0, 156, 6, 0, 0, + 14, 0, 2, 0, 172, 6, 0, 0, 14, 0, 2, 0, - 176, 6, 0, 0, 65, 0, - 0, 0, 192, 6, 0, 0, - 65, 0, 0, 0, 208, 6, + 188, 6, 0, 0, 65, 0, + 0, 0, 204, 6, 0, 0, + 65, 0, 0, 0, 220, 6, 0, 0, 65, 0, 0, 0, - 224, 6, 0, 0, 66, 0, - 0, 0, 240, 6, 0, 0, - 66, 0, 0, 0, 0, 7, + 236, 6, 0, 0, 66, 0, + 0, 0, 252, 6, 0, 0, + 66, 0, 0, 0, 12, 7, 0, 0, 81, 0, 0, 0, - 12, 7, 0, 0, 81, 0, - 0, 0, 28, 7, 0, 0, - 81, 0, 0, 0, 44, 7, + 24, 7, 0, 0, 81, 0, + 0, 0, 40, 7, 0, 0, + 81, 0, 0, 0, 56, 7, 0, 0, 71, 0, 0, 0, - 64, 7, 0, 0, 71, 0, - 0, 0, 80, 7, 0, 0, - 71, 0, 0, 0, 96, 7, + 76, 7, 0, 0, 71, 0, + 0, 0, 92, 7, 0, 0, + 71, 0, 0, 0, 108, 7, 0, 0, 102, 0, 0, 0, - 112, 7, 0, 0, 102, 0, - 0, 0, 132, 7, 0, 0, - 46, 0, 1, 0, 144, 7, + 124, 7, 0, 0, 102, 0, + 0, 0, 144, 7, 0, 0, + 46, 0, 1, 0, 156, 7, 0, 0, 77, 0, 0, 0, - 156, 7, 0, 0, 104, 0, - 0, 0, 168, 7, 0, 0, + 168, 7, 0, 0, 104, 0, + 0, 0, 180, 7, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, @@ -420,7 +420,9 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 18, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc index f2353110..6ca1b742 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc @@ -49,13 +49,13 @@ dcl_texcoord1 v1 // vin<4,5,6> dcl_texcoord2 v2 // vin<7,8> -#line 67 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 67 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, v1, c11 dp3 r0.y, v1, c12 dp3 r0.z, v1, c13 nrm r1.xyz, r0 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r0.x, -c4, r1 // ::dotL<0> #line 39 @@ -67,7 +67,7 @@ mov r2.xyz, c2 // Parameters::DiffuseColor<0,1,2> mad oT0.xyz, r0, r2, c3 // ::VSEnvMapOneLightFresnel<0,1,2> -#line 71 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 71 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp4 oPos.z, v0, c16 // ::VSEnvMapOneLightFresnel<15> #line 65 @@ -85,12 +85,12 @@ pow r1.w, r0.x, c1.y mul oT1.xyz, r1.w, c1.x // ::VSEnvMapOneLightFresnel<4,5,6> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, v0, c7 max r0.x, r0.x, c18.x min oT1.w, r0.x, c18.y // ::VSEnvMapOneLightFresnel<7> -#line 81 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 81 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" dp3 r0.x, -r2, r1 add r0.x, r0.x, r0.x mad oT3.xyz, r1, -r0.x, -r2 // ::VSEnvMapOneLightFresnel<10,11,12> @@ -104,10 +104,10 @@ mad oPos.xy, r0.z, c0, r0 // ::VSEnvMapOneLightFresnel<13,14> mov oPos.w, r0.z // ::VSEnvMapOneLightFresnel<16> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c2.w // ::VSEnvMapOneLightFresnel<3> -#line 111 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" +#line 111 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\EnvironmentMapEffect.fx" mov oT2.xy, v2 // ::VSEnvMapOneLightFresnel<8,9> // approximately 41 instruction slots used @@ -164,17 +164,17 @@ ret const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = { - 68, 88, 66, 67, 60, 1, - 73, 10, 62, 42, 102, 216, - 224, 107, 79, 152, 202, 62, - 59, 32, 1, 0, 0, 0, - 232, 14, 0, 0, 4, 0, + 68, 88, 66, 67, 18, 68, + 191, 149, 221, 33, 70, 57, + 87, 75, 188, 69, 243, 226, + 132, 104, 1, 0, 0, 0, + 244, 14, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 12, 9, 0, 0, 208, 13, - 0, 0, 68, 14, 0, 0, - 65, 111, 110, 57, 212, 8, - 0, 0, 212, 8, 0, 0, - 0, 2, 254, 255, 112, 8, + 24, 9, 0, 0, 220, 13, + 0, 0, 80, 14, 0, 0, + 65, 111, 110, 57, 224, 8, + 0, 0, 224, 8, 0, 0, + 0, 2, 254, 255, 124, 8, 0, 0, 100, 0, 0, 0, 5, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, @@ -191,14 +191,14 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = 7, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 130, 1, 68, 66, 85, 71, + 133, 1, 68, 66, 85, 71, 40, 0, 0, 0, 220, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 1, 0, 0, 39, 0, 0, 0, 24, 1, 0, 0, 11, 0, 0, 0, 0, 5, 0, 0, - 132, 2, 0, 0, 67, 58, + 132, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -212,7 +212,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = 118, 105, 114, 111, 110, 109, 101, 110, 116, 77, 97, 112, 69, 102, 102, 101, 99, 116, - 46, 102, 120, 0, 67, 58, + 46, 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -224,7 +224,7 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = 99, 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, - 46, 102, 120, 104, 0, 67, + 46, 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, @@ -239,58 +239,58 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = 102, 120, 104, 0, 40, 0, 0, 0, 124, 0, 0, 0, 197, 0, 0, 0, 0, 0, - 255, 255, 16, 6, 0, 0, - 0, 0, 255, 255, 40, 6, + 255, 255, 28, 6, 0, 0, + 0, 0, 255, 255, 52, 6, 0, 0, 0, 0, 255, 255, - 52, 6, 0, 0, 0, 0, - 255, 255, 64, 6, 0, 0, - 67, 0, 0, 0, 76, 6, + 64, 6, 0, 0, 0, 0, + 255, 255, 76, 6, 0, 0, + 67, 0, 0, 0, 88, 6, 0, 0, 67, 0, 0, 0, - 92, 6, 0, 0, 67, 0, - 0, 0, 108, 6, 0, 0, - 67, 0, 0, 0, 124, 6, + 104, 6, 0, 0, 67, 0, + 0, 0, 120, 6, 0, 0, + 67, 0, 0, 0, 136, 6, 0, 0, 36, 0, 1, 0, - 136, 6, 0, 0, 39, 0, - 1, 0, 152, 6, 0, 0, - 41, 0, 1, 0, 168, 6, + 148, 6, 0, 0, 39, 0, + 1, 0, 164, 6, 0, 0, + 41, 0, 1, 0, 180, 6, 0, 0, 46, 0, 1, 0, - 184, 6, 0, 0, 46, 0, - 1, 0, 200, 6, 0, 0, - 46, 0, 1, 0, 212, 6, + 196, 6, 0, 0, 46, 0, + 1, 0, 212, 6, 0, 0, + 46, 0, 1, 0, 224, 6, 0, 0, 71, 0, 0, 0, - 232, 6, 0, 0, 65, 0, - 0, 0, 248, 6, 0, 0, - 65, 0, 0, 0, 8, 7, + 244, 6, 0, 0, 65, 0, + 0, 0, 4, 7, 0, 0, + 65, 0, 0, 0, 20, 7, 0, 0, 65, 0, 0, 0, - 24, 7, 0, 0, 66, 0, - 0, 0, 40, 7, 0, 0, - 66, 0, 0, 0, 56, 7, + 36, 7, 0, 0, 66, 0, + 0, 0, 52, 7, 0, 0, + 66, 0, 0, 0, 68, 7, 0, 0, 55, 0, 0, 0, - 68, 7, 0, 0, 57, 0, - 0, 0, 84, 7, 0, 0, - 57, 0, 0, 0, 96, 7, + 80, 7, 0, 0, 57, 0, + 0, 0, 96, 7, 0, 0, + 57, 0, 0, 0, 108, 7, 0, 0, 57, 0, 0, 0, - 112, 7, 0, 0, 57, 0, - 0, 0, 128, 7, 0, 0, - 57, 0, 0, 0, 144, 7, + 124, 7, 0, 0, 57, 0, + 0, 0, 140, 7, 0, 0, + 57, 0, 0, 0, 156, 7, 0, 0, 14, 0, 2, 0, - 160, 7, 0, 0, 14, 0, - 2, 0, 176, 7, 0, 0, - 14, 0, 2, 0, 192, 7, + 172, 7, 0, 0, 14, 0, + 2, 0, 188, 7, 0, 0, + 14, 0, 2, 0, 204, 7, 0, 0, 81, 0, 0, 0, - 208, 7, 0, 0, 81, 0, - 0, 0, 224, 7, 0, 0, - 81, 0, 0, 0, 240, 7, + 220, 7, 0, 0, 81, 0, + 0, 0, 236, 7, 0, 0, + 81, 0, 0, 0, 252, 7, 0, 0, 71, 0, 0, 0, - 4, 8, 0, 0, 71, 0, - 0, 0, 20, 8, 0, 0, - 71, 0, 0, 0, 36, 8, + 16, 8, 0, 0, 71, 0, + 0, 0, 32, 8, 0, 0, + 71, 0, 0, 0, 48, 8, 0, 0, 109, 0, 0, 0, - 52, 8, 0, 0, 109, 0, - 0, 0, 72, 8, 0, 0, - 46, 0, 1, 0, 84, 8, + 64, 8, 0, 0, 109, 0, + 0, 0, 84, 8, 0, 0, + 46, 0, 1, 0, 96, 8, 0, 0, 111, 0, 0, 0, - 96, 8, 0, 0, 80, 97, + 108, 8, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, 115, 101, 67, 111, @@ -448,7 +448,9 @@ const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 18, 0, 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc index b881d6b5..b3dc3b02 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc @@ -44,13 +44,13 @@ dcl t3 // pin<9,10,11,12> dcl_2d s0 -#line 233 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 233 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" texld r0, t0, s0 #line 236 nrm r1.xyz, t2 // ::worldNormal<0,1,2> -#line 36 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 36 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, -c3, r1 // ::dotL<0> dp3 r2.y, -c4, r1 // ::dotL<1> dp3 r2.z, -c5, r1 // ::dotL<2> @@ -59,12 +59,12 @@ cmp r3.xyz, r2, c14.x, c14.y // ::zeroL<0,1,2> mul r2.xyz, r2, r3 // ::diffuse<0,1,2> -#line 235 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 235 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" add r4.xyz, -t1, c12 dp3 r1.w, r4, r4 rsq r1.w, r1.w -#line 33 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 33 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mad r5.xyz, r4, r1.w, -c3 nrm r6.xyz, r5 // ::halfVectors<0,1,2> @@ -106,20 +106,20 @@ mad r1.xyz, r3.w, c11, r1 mul r1.xyz, r1, c2 // ::result<3,4,5> -#line 233 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 233 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0, r0, t3 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mul r1.xyz, r0.w, r1 -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mul r3.xyz, r2.y, c7 mad r3.xyz, r2.x, c6, r3 mad r2.xyz, r2.z, c8, r3 mov r3.xyz, c0 // Parameters::DiffuseColor<0,1,2> mad r2.xyz, r2, r3, c1 // ::result<0,1,2> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, r0, r2, r1 // AddSpecular::color<0,1,2> #line 20 @@ -191,17 +191,17 @@ ret const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = { - 68, 88, 66, 67, 167, 255, - 138, 170, 18, 129, 91, 123, - 243, 168, 145, 228, 204, 13, - 248, 166, 1, 0, 0, 0, - 24, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 105, 97, + 0, 135, 240, 202, 102, 138, + 57, 48, 28, 167, 230, 153, + 11, 141, 1, 0, 0, 0, + 36, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 16, 10, 0, 0, 100, 16, - 0, 0, 228, 16, 0, 0, - 65, 111, 110, 57, 216, 9, - 0, 0, 216, 9, 0, 0, - 0, 2, 255, 255, 164, 9, + 28, 10, 0, 0, 112, 16, + 0, 0, 240, 16, 0, 0, + 65, 111, 110, 57, 228, 9, + 0, 0, 228, 9, 0, 0, + 0, 2, 255, 255, 176, 9, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -210,14 +210,14 @@ const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 165, 1, 68, 66, 85, 71, + 168, 1, 68, 66, 85, 71, 40, 0, 0, 0, 104, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 49, 0, 0, 0, 20, 1, 0, 0, 14, 0, 0, 0, 80, 5, 0, 0, - 208, 2, 0, 0, 67, 58, + 208, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -230,7 +230,7 @@ const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -242,7 +242,7 @@ const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -257,71 +257,71 @@ const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 156, 6, + 0, 0, 255, 255, 168, 6, 0, 0, 0, 0, 255, 255, - 180, 6, 0, 0, 0, 0, - 255, 255, 192, 6, 0, 0, - 0, 0, 255, 255, 204, 6, + 192, 6, 0, 0, 0, 0, + 255, 255, 204, 6, 0, 0, + 0, 0, 255, 255, 216, 6, 0, 0, 0, 0, 255, 255, - 216, 6, 0, 0, 0, 0, - 255, 255, 228, 6, 0, 0, - 233, 0, 0, 0, 240, 6, + 228, 6, 0, 0, 0, 0, + 255, 255, 240, 6, 0, 0, + 233, 0, 0, 0, 252, 6, 0, 0, 236, 0, 0, 0, - 0, 7, 0, 0, 36, 0, - 1, 0, 12, 7, 0, 0, - 36, 0, 1, 0, 28, 7, + 12, 7, 0, 0, 36, 0, + 1, 0, 24, 7, 0, 0, + 36, 0, 1, 0, 40, 7, 0, 0, 36, 0, 1, 0, - 44, 7, 0, 0, 39, 0, - 1, 0, 60, 7, 0, 0, - 41, 0, 1, 0, 80, 7, + 56, 7, 0, 0, 39, 0, + 1, 0, 72, 7, 0, 0, + 41, 0, 1, 0, 92, 7, 0, 0, 235, 0, 0, 0, - 96, 7, 0, 0, 235, 0, - 0, 0, 112, 7, 0, 0, - 235, 0, 0, 0, 128, 7, + 108, 7, 0, 0, 235, 0, + 0, 0, 124, 7, 0, 0, + 235, 0, 0, 0, 140, 7, 0, 0, 33, 0, 1, 0, - 140, 7, 0, 0, 33, 0, - 1, 0, 160, 7, 0, 0, - 37, 0, 1, 0, 172, 7, + 152, 7, 0, 0, 33, 0, + 1, 0, 172, 7, 0, 0, + 37, 0, 1, 0, 184, 7, 0, 0, 33, 0, 1, 0, - 188, 7, 0, 0, 33, 0, - 1, 0, 208, 7, 0, 0, - 33, 0, 1, 0, 228, 7, + 200, 7, 0, 0, 33, 0, + 1, 0, 220, 7, 0, 0, + 33, 0, 1, 0, 240, 7, 0, 0, 37, 0, 1, 0, - 240, 7, 0, 0, 33, 0, - 1, 0, 0, 8, 0, 0, - 37, 0, 1, 0, 12, 8, + 252, 7, 0, 0, 33, 0, + 1, 0, 12, 8, 0, 0, + 37, 0, 1, 0, 24, 8, 0, 0, 42, 0, 1, 0, - 28, 8, 0, 0, 42, 0, - 1, 0, 44, 8, 0, 0, - 42, 0, 1, 0, 64, 8, + 40, 8, 0, 0, 42, 0, + 1, 0, 56, 8, 0, 0, + 42, 0, 1, 0, 76, 8, 0, 0, 42, 0, 1, 0, - 76, 8, 0, 0, 42, 0, - 1, 0, 88, 8, 0, 0, - 42, 0, 1, 0, 100, 8, + 88, 8, 0, 0, 42, 0, + 1, 0, 100, 8, 0, 0, + 42, 0, 1, 0, 112, 8, 0, 0, 42, 0, 1, 0, - 116, 8, 0, 0, 47, 0, - 1, 0, 128, 8, 0, 0, - 42, 0, 1, 0, 144, 8, + 128, 8, 0, 0, 47, 0, + 1, 0, 140, 8, 0, 0, + 42, 0, 1, 0, 156, 8, 0, 0, 42, 0, 1, 0, - 156, 8, 0, 0, 47, 0, - 1, 0, 168, 8, 0, 0, - 47, 0, 1, 0, 188, 8, + 168, 8, 0, 0, 47, 0, + 1, 0, 180, 8, 0, 0, + 47, 0, 1, 0, 200, 8, 0, 0, 47, 0, 1, 0, - 208, 8, 0, 0, 233, 0, - 0, 0, 224, 8, 0, 0, - 26, 0, 2, 0, 240, 8, + 220, 8, 0, 0, 233, 0, + 0, 0, 236, 8, 0, 0, + 26, 0, 2, 0, 252, 8, 0, 0, 46, 0, 1, 0, - 0, 9, 0, 0, 46, 0, - 1, 0, 16, 9, 0, 0, - 46, 0, 1, 0, 36, 9, + 12, 9, 0, 0, 46, 0, + 1, 0, 28, 9, 0, 0, + 46, 0, 1, 0, 48, 9, 0, 0, 46, 0, 1, 0, - 56, 9, 0, 0, 46, 0, - 1, 0, 68, 9, 0, 0, - 26, 0, 2, 0, 88, 9, + 68, 9, 0, 0, 46, 0, + 1, 0, 80, 9, 0, 0, + 26, 0, 2, 0, 100, 9, 0, 0, 20, 0, 2, 0, - 108, 9, 0, 0, 20, 0, - 2, 0, 128, 9, 0, 0, - 20, 0, 2, 0, 148, 9, + 120, 9, 0, 0, 20, 0, + 2, 0, 140, 9, 0, 0, + 20, 0, 2, 0, 160, 9, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -490,7 +490,9 @@ const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 14, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc index 36006399..dea07244 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc @@ -41,11 +41,11 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 210 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 210 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" texld r0, t2, s0 mul r0, r0, t0 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r1.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> #line 20 @@ -75,17 +75,17 @@ ret const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = { - 68, 88, 66, 67, 136, 182, - 245, 134, 252, 10, 70, 248, - 112, 36, 89, 190, 185, 222, - 52, 160, 1, 0, 0, 0, - 144, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 113, 147, + 72, 239, 18, 199, 152, 77, + 78, 131, 248, 237, 51, 196, + 57, 113, 1, 0, 0, 0, + 156, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 180, 3, 0, 0, 244, 4, - 0, 0, 92, 5, 0, 0, - 65, 111, 110, 57, 124, 3, - 0, 0, 124, 3, 0, 0, - 0, 2, 255, 255, 72, 3, + 192, 3, 0, 0, 0, 5, + 0, 0, 104, 5, 0, 0, + 65, 111, 110, 57, 136, 3, + 0, 0, 136, 3, 0, 0, + 0, 2, 255, 255, 84, 3, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, @@ -94,14 +94,14 @@ const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = 0, 0, 13, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 169, 0, 68, 66, 85, 71, + 172, 0, 68, 66, 85, 71, 40, 0, 0, 0, 120, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 10, 0, 0, 0, 196, 0, 0, 0, 5, 0, 0, 0, 20, 2, 0, 0, - 20, 1, 0, 0, 67, 58, + 20, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -114,7 +114,7 @@ const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -128,19 +128,19 @@ const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = 109, 111, 110, 46, 102, 120, 104, 0, 40, 0, 0, 0, 117, 0, 0, 0, 0, 0, - 255, 255, 172, 2, 0, 0, - 0, 0, 255, 255, 184, 2, + 255, 255, 184, 2, 0, 0, + 0, 0, 255, 255, 196, 2, 0, 0, 0, 0, 255, 255, - 196, 2, 0, 0, 0, 0, - 255, 255, 208, 2, 0, 0, - 210, 0, 0, 0, 220, 2, + 208, 2, 0, 0, 0, 0, + 255, 255, 220, 2, 0, 0, + 210, 0, 0, 0, 232, 2, 0, 0, 210, 0, 0, 0, - 236, 2, 0, 0, 26, 0, - 1, 0, 252, 2, 0, 0, - 20, 0, 1, 0, 16, 3, + 248, 2, 0, 0, 26, 0, + 1, 0, 8, 3, 0, 0, + 20, 0, 1, 0, 28, 3, 0, 0, 20, 0, 1, 0, - 36, 3, 0, 0, 20, 0, - 1, 0, 56, 3, 0, 0, + 48, 3, 0, 0, 20, 0, + 1, 0, 68, 3, 0, 0, 80, 83, 83, 107, 105, 110, 110, 101, 100, 86, 101, 114, 116, 101, 120, 76, 105, 103, @@ -206,7 +206,9 @@ const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc index 568a2304..5bf1fccb 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc @@ -34,11 +34,11 @@ dcl t2.xy // pin<8,9> dcl_2d s0 -#line 222 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 222 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" texld r0, t2, s0 mul r0, r0, t0 // ::color<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" mad r0.xyz, t1, r0.w, r0 // AddSpecular::color<0,1,2> mov oC0, r0 // ::PSSkinnedVertexLightingNoFog<0,1,2,3> @@ -61,31 +61,31 @@ ret const BYTE SkinnedEffect_PSSkinnedVertexLightingNoFog[] = { - 68, 88, 66, 67, 106, 186, - 183, 34, 48, 16, 115, 237, - 74, 230, 89, 81, 140, 120, - 101, 85, 1, 0, 0, 0, - 204, 4, 0, 0, 4, 0, + 68, 88, 66, 67, 98, 30, + 247, 36, 254, 70, 12, 1, + 88, 124, 67, 4, 132, 79, + 102, 111, 1, 0, 0, 0, + 216, 4, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 80, 3, 0, 0, 48, 4, - 0, 0, 152, 4, 0, 0, - 65, 111, 110, 57, 24, 3, - 0, 0, 24, 3, 0, 0, - 0, 2, 255, 255, 240, 2, + 92, 3, 0, 0, 60, 4, + 0, 0, 164, 4, 0, 0, + 65, 111, 110, 57, 36, 3, + 0, 0, 36, 3, 0, 0, + 0, 2, 255, 255, 252, 2, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 157, 0, 68, 66, 85, 71, + 160, 0, 68, 66, 85, 71, 40, 0, 0, 0, 72, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 8, 0, 0, 0, 196, 0, 0, 0, 4, 0, 0, 0, 248, 1, 0, 0, - 4, 1, 0, 0, 67, 58, + 4, 1, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -98,7 +98,7 @@ const BYTE SkinnedEffect_PSSkinnedVertexLightingNoFog[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -112,16 +112,16 @@ const BYTE SkinnedEffect_PSSkinnedVertexLightingNoFog[] = 109, 111, 110, 46, 102, 120, 104, 0, 40, 0, 0, 0, 117, 0, 0, 0, 0, 0, - 255, 255, 124, 2, 0, 0, - 0, 0, 255, 255, 136, 2, + 255, 255, 136, 2, 0, 0, + 0, 0, 255, 255, 148, 2, 0, 0, 0, 0, 255, 255, - 148, 2, 0, 0, 0, 0, - 255, 255, 160, 2, 0, 0, - 222, 0, 0, 0, 172, 2, + 160, 2, 0, 0, 0, 0, + 255, 255, 172, 2, 0, 0, + 222, 0, 0, 0, 184, 2, 0, 0, 222, 0, 0, 0, - 188, 2, 0, 0, 26, 0, - 1, 0, 204, 2, 0, 0, - 26, 0, 1, 0, 224, 2, + 200, 2, 0, 0, 26, 0, + 1, 0, 216, 2, 0, 0, + 26, 0, 1, 0, 236, 2, 0, 0, 80, 83, 83, 107, 105, 110, 110, 101, 100, 86, 101, 114, 116, 101, 120, 76, @@ -182,7 +182,9 @@ const BYTE SkinnedEffect_PSSkinnedVertexLightingNoFog[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc index fa07bdf3..bd9ee13c 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0, v3, c243.x mova a0, r0.yxzw mul r1, v4.y, c26[a0.x] @@ -76,7 +76,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -121,24 +121,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedOneLightFourBones<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedOneLightFourBones<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 141 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 141 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedOneLightFourBones<10,11> mov oPos.w, r0.x // ::VSSkinnedOneLightFourBones<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedOneLightFourBones<3> -#line 145 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 145 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedOneLightFourBones<8,9> // approximately 63 instruction slots used @@ -217,17 +217,17 @@ ret const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = { - 68, 88, 66, 67, 203, 46, - 72, 203, 82, 54, 50, 161, - 103, 172, 86, 28, 64, 194, - 240, 31, 1, 0, 0, 0, - 36, 22, 0, 0, 4, 0, + 68, 88, 66, 67, 240, 37, + 220, 253, 15, 164, 196, 10, + 27, 205, 118, 81, 151, 201, + 210, 229, 1, 0, 0, 0, + 48, 22, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 232, 12, 0, 0, 216, 20, - 0, 0, 152, 21, 0, 0, - 65, 111, 110, 57, 176, 12, - 0, 0, 176, 12, 0, 0, - 0, 2, 254, 255, 124, 12, + 244, 12, 0, 0, 228, 20, + 0, 0, 164, 21, 0, 0, + 65, 111, 110, 57, 188, 12, + 0, 0, 188, 12, 0, 0, + 0, 2, 254, 255, 136, 12, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -236,14 +236,14 @@ const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 29, 2, 68, 66, 85, 71, + 32, 2, 68, 66, 85, 71, 40, 0, 0, 0, 72, 8, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 61, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 28, 7, 0, 0, - 48, 3, 0, 0, 67, 58, + 48, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -256,7 +256,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -268,7 +268,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -283,87 +283,87 @@ const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 124, 8, + 0, 0, 255, 255, 136, 8, 0, 0, 0, 0, 255, 255, - 148, 8, 0, 0, 0, 0, - 255, 255, 160, 8, 0, 0, - 0, 0, 255, 255, 172, 8, + 160, 8, 0, 0, 0, 0, + 255, 255, 172, 8, 0, 0, + 0, 0, 255, 255, 184, 8, 0, 0, 0, 0, 255, 255, - 184, 8, 0, 0, 0, 0, - 255, 255, 196, 8, 0, 0, - 52, 0, 0, 0, 208, 8, + 196, 8, 0, 0, 0, 0, + 255, 255, 208, 8, 0, 0, + 52, 0, 0, 0, 220, 8, 0, 0, 52, 0, 0, 0, - 224, 8, 0, 0, 52, 0, - 0, 0, 236, 8, 0, 0, - 52, 0, 0, 0, 0, 9, + 236, 8, 0, 0, 52, 0, + 0, 0, 248, 8, 0, 0, + 52, 0, 0, 0, 12, 9, 0, 0, 52, 0, 0, 0, - 24, 9, 0, 0, 52, 0, - 0, 0, 48, 9, 0, 0, - 56, 0, 0, 0, 72, 9, + 36, 9, 0, 0, 52, 0, + 0, 0, 60, 9, 0, 0, + 56, 0, 0, 0, 84, 9, 0, 0, 55, 0, 0, 0, - 88, 9, 0, 0, 52, 0, - 0, 0, 104, 9, 0, 0, - 52, 0, 0, 0, 124, 9, + 100, 9, 0, 0, 52, 0, + 0, 0, 116, 9, 0, 0, + 52, 0, 0, 0, 136, 9, 0, 0, 52, 0, 0, 0, - 144, 9, 0, 0, 52, 0, - 0, 0, 168, 9, 0, 0, - 52, 0, 0, 0, 192, 9, + 156, 9, 0, 0, 52, 0, + 0, 0, 180, 9, 0, 0, + 52, 0, 0, 0, 204, 9, 0, 0, 52, 0, 0, 0, - 216, 9, 0, 0, 52, 0, - 0, 0, 240, 9, 0, 0, - 52, 0, 0, 0, 8, 10, + 228, 9, 0, 0, 52, 0, + 0, 0, 252, 9, 0, 0, + 52, 0, 0, 0, 20, 10, 0, 0, 56, 0, 0, 0, - 32, 10, 0, 0, 55, 0, - 0, 0, 48, 10, 0, 0, - 56, 0, 0, 0, 64, 10, + 44, 10, 0, 0, 55, 0, + 0, 0, 60, 10, 0, 0, + 56, 0, 0, 0, 76, 10, 0, 0, 55, 0, 0, 0, - 80, 10, 0, 0, 59, 0, - 1, 0, 96, 10, 0, 0, - 59, 0, 1, 0, 112, 10, + 92, 10, 0, 0, 59, 0, + 1, 0, 108, 10, 0, 0, + 59, 0, 1, 0, 124, 10, 0, 0, 59, 0, 1, 0, - 128, 10, 0, 0, 59, 0, - 1, 0, 144, 10, 0, 0, - 36, 0, 1, 0, 156, 10, + 140, 10, 0, 0, 59, 0, + 1, 0, 156, 10, 0, 0, + 36, 0, 1, 0, 168, 10, 0, 0, 39, 0, 1, 0, - 172, 10, 0, 0, 41, 0, - 1, 0, 188, 10, 0, 0, - 46, 0, 1, 0, 204, 10, + 184, 10, 0, 0, 41, 0, + 1, 0, 200, 10, 0, 0, + 46, 0, 1, 0, 216, 10, 0, 0, 46, 0, 1, 0, - 220, 10, 0, 0, 46, 0, - 1, 0, 232, 10, 0, 0, - 57, 0, 1, 0, 252, 10, + 232, 10, 0, 0, 46, 0, + 1, 0, 244, 10, 0, 0, + 57, 0, 1, 0, 8, 11, 0, 0, 57, 0, 1, 0, - 8, 11, 0, 0, 57, 0, - 1, 0, 24, 11, 0, 0, - 57, 0, 1, 0, 40, 11, + 20, 11, 0, 0, 57, 0, + 1, 0, 36, 11, 0, 0, + 57, 0, 1, 0, 52, 11, 0, 0, 58, 0, 1, 0, - 56, 11, 0, 0, 58, 0, - 1, 0, 72, 11, 0, 0, - 33, 0, 1, 0, 84, 11, + 68, 11, 0, 0, 58, 0, + 1, 0, 84, 11, 0, 0, + 33, 0, 1, 0, 96, 11, 0, 0, 33, 0, 1, 0, - 100, 11, 0, 0, 37, 0, - 1, 0, 112, 11, 0, 0, - 42, 0, 1, 0, 128, 11, + 112, 11, 0, 0, 37, 0, + 1, 0, 124, 11, 0, 0, + 42, 0, 1, 0, 140, 11, 0, 0, 42, 0, 1, 0, - 144, 11, 0, 0, 42, 0, - 1, 0, 160, 11, 0, 0, - 47, 0, 1, 0, 176, 11, + 156, 11, 0, 0, 42, 0, + 1, 0, 172, 11, 0, 0, + 47, 0, 1, 0, 188, 11, 0, 0, 47, 0, 1, 0, - 192, 11, 0, 0, 63, 0, - 1, 0, 208, 11, 0, 0, - 14, 0, 2, 0, 224, 11, + 204, 11, 0, 0, 63, 0, + 1, 0, 220, 11, 0, 0, + 14, 0, 2, 0, 236, 11, 0, 0, 14, 0, 2, 0, - 240, 11, 0, 0, 14, 0, - 2, 0, 0, 12, 0, 0, - 63, 0, 1, 0, 16, 12, + 252, 11, 0, 0, 14, 0, + 2, 0, 12, 12, 0, 0, + 63, 0, 1, 0, 28, 12, 0, 0, 63, 0, 1, 0, - 32, 12, 0, 0, 63, 0, - 1, 0, 48, 12, 0, 0, - 141, 0, 0, 0, 64, 12, + 44, 12, 0, 0, 63, 0, + 1, 0, 60, 12, 0, 0, + 141, 0, 0, 0, 76, 12, 0, 0, 141, 0, 0, 0, - 84, 12, 0, 0, 46, 0, - 1, 0, 96, 12, 0, 0, - 145, 0, 0, 0, 108, 12, + 96, 12, 0, 0, 46, 0, + 1, 0, 108, 12, 0, 0, + 145, 0, 0, 0, 120, 12, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -596,7 +596,9 @@ const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc index 9a87e6d2..ee828c95 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.x, v3.x, c243.x mova a0.x, r0.x mul r0, v4.x, c26[a0.x] // ::skinning<0,3,6,9> @@ -67,7 +67,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -112,24 +112,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedOneLightOneBone<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedOneLightOneBone<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 109 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 109 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedOneLightOneBone<10,11> mov oPos.w, r0.x // ::VSSkinnedOneLightOneBone<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedOneLightOneBone<3> -#line 113 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 113 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedOneLightOneBone<8,9> // approximately 54 instruction slots used @@ -199,17 +199,17 @@ ret const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = { - 68, 88, 66, 67, 120, 170, - 51, 155, 98, 149, 240, 251, - 11, 114, 75, 24, 138, 47, - 241, 16, 1, 0, 0, 0, - 0, 19, 0, 0, 4, 0, + 68, 88, 66, 67, 25, 255, + 35, 167, 193, 235, 165, 157, + 195, 174, 52, 60, 201, 68, + 164, 115, 1, 0, 0, 0, + 12, 19, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 128, 11, 0, 0, 180, 17, - 0, 0, 116, 18, 0, 0, - 65, 111, 110, 57, 72, 11, - 0, 0, 72, 11, 0, 0, - 0, 2, 254, 255, 20, 11, + 140, 11, 0, 0, 192, 17, + 0, 0, 128, 18, 0, 0, + 65, 111, 110, 57, 84, 11, + 0, 0, 84, 11, 0, 0, + 0, 2, 254, 255, 32, 11, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -218,14 +218,14 @@ const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 249, 1, 68, 66, 85, 71, + 252, 1, 68, 66, 85, 71, 40, 0, 0, 0, 184, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 52, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 140, 6, 0, 0, - 232, 2, 0, 0, 67, 58, + 232, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -238,7 +238,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -250,7 +250,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -265,75 +265,75 @@ const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 236, 7, + 0, 0, 255, 255, 248, 7, 0, 0, 0, 0, 255, 255, - 4, 8, 0, 0, 0, 0, - 255, 255, 16, 8, 0, 0, - 0, 0, 255, 255, 28, 8, + 16, 8, 0, 0, 0, 0, + 255, 255, 28, 8, 0, 0, + 0, 0, 255, 255, 40, 8, 0, 0, 0, 0, 255, 255, - 40, 8, 0, 0, 0, 0, - 255, 255, 52, 8, 0, 0, - 52, 0, 0, 0, 64, 8, + 52, 8, 0, 0, 0, 0, + 255, 255, 64, 8, 0, 0, + 52, 0, 0, 0, 76, 8, 0, 0, 52, 0, 0, 0, - 80, 8, 0, 0, 52, 0, - 0, 0, 92, 8, 0, 0, - 56, 0, 0, 0, 112, 8, + 92, 8, 0, 0, 52, 0, + 0, 0, 104, 8, 0, 0, + 56, 0, 0, 0, 124, 8, 0, 0, 55, 0, 0, 0, - 128, 8, 0, 0, 52, 0, - 0, 0, 144, 8, 0, 0, - 52, 0, 0, 0, 164, 8, + 140, 8, 0, 0, 52, 0, + 0, 0, 156, 8, 0, 0, + 52, 0, 0, 0, 176, 8, 0, 0, 56, 0, 0, 0, - 184, 8, 0, 0, 55, 0, - 0, 0, 200, 8, 0, 0, - 56, 0, 0, 0, 216, 8, + 196, 8, 0, 0, 55, 0, + 0, 0, 212, 8, 0, 0, + 56, 0, 0, 0, 228, 8, 0, 0, 55, 0, 0, 0, - 232, 8, 0, 0, 59, 0, - 1, 0, 248, 8, 0, 0, - 59, 0, 1, 0, 8, 9, + 244, 8, 0, 0, 59, 0, + 1, 0, 4, 9, 0, 0, + 59, 0, 1, 0, 20, 9, 0, 0, 59, 0, 1, 0, - 24, 9, 0, 0, 59, 0, - 1, 0, 40, 9, 0, 0, - 36, 0, 1, 0, 52, 9, + 36, 9, 0, 0, 59, 0, + 1, 0, 52, 9, 0, 0, + 36, 0, 1, 0, 64, 9, 0, 0, 39, 0, 1, 0, - 68, 9, 0, 0, 41, 0, - 1, 0, 84, 9, 0, 0, - 46, 0, 1, 0, 100, 9, + 80, 9, 0, 0, 41, 0, + 1, 0, 96, 9, 0, 0, + 46, 0, 1, 0, 112, 9, 0, 0, 46, 0, 1, 0, - 116, 9, 0, 0, 46, 0, - 1, 0, 128, 9, 0, 0, - 57, 0, 1, 0, 148, 9, + 128, 9, 0, 0, 46, 0, + 1, 0, 140, 9, 0, 0, + 57, 0, 1, 0, 160, 9, 0, 0, 57, 0, 1, 0, - 160, 9, 0, 0, 57, 0, - 1, 0, 176, 9, 0, 0, - 57, 0, 1, 0, 192, 9, + 172, 9, 0, 0, 57, 0, + 1, 0, 188, 9, 0, 0, + 57, 0, 1, 0, 204, 9, 0, 0, 58, 0, 1, 0, - 208, 9, 0, 0, 58, 0, - 1, 0, 224, 9, 0, 0, - 33, 0, 1, 0, 236, 9, + 220, 9, 0, 0, 58, 0, + 1, 0, 236, 9, 0, 0, + 33, 0, 1, 0, 248, 9, 0, 0, 33, 0, 1, 0, - 252, 9, 0, 0, 37, 0, - 1, 0, 8, 10, 0, 0, - 42, 0, 1, 0, 24, 10, + 8, 10, 0, 0, 37, 0, + 1, 0, 20, 10, 0, 0, + 42, 0, 1, 0, 36, 10, 0, 0, 42, 0, 1, 0, - 40, 10, 0, 0, 42, 0, - 1, 0, 56, 10, 0, 0, - 47, 0, 1, 0, 72, 10, + 52, 10, 0, 0, 42, 0, + 1, 0, 68, 10, 0, 0, + 47, 0, 1, 0, 84, 10, 0, 0, 47, 0, 1, 0, - 88, 10, 0, 0, 63, 0, - 1, 0, 104, 10, 0, 0, - 14, 0, 2, 0, 120, 10, + 100, 10, 0, 0, 63, 0, + 1, 0, 116, 10, 0, 0, + 14, 0, 2, 0, 132, 10, 0, 0, 14, 0, 2, 0, - 136, 10, 0, 0, 14, 0, - 2, 0, 152, 10, 0, 0, - 63, 0, 1, 0, 168, 10, + 148, 10, 0, 0, 14, 0, + 2, 0, 164, 10, 0, 0, + 63, 0, 1, 0, 180, 10, 0, 0, 63, 0, 1, 0, - 184, 10, 0, 0, 63, 0, - 1, 0, 200, 10, 0, 0, - 109, 0, 0, 0, 216, 10, + 196, 10, 0, 0, 63, 0, + 1, 0, 212, 10, 0, 0, + 109, 0, 0, 0, 228, 10, 0, 0, 109, 0, 0, 0, - 236, 10, 0, 0, 46, 0, - 1, 0, 248, 10, 0, 0, - 113, 0, 0, 0, 4, 11, + 248, 10, 0, 0, 46, 0, + 1, 0, 4, 11, 0, 0, + 113, 0, 0, 0, 16, 11, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -554,7 +554,9 @@ const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc index 7486b02a..ec2ee99a 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.xy, v3, c243.x mova a0.xy, r0.yxzw mul r0, v4.y, c26[a0.x] @@ -70,7 +70,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -115,24 +115,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedOneLightTwoBones<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedOneLightTwoBones<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 125 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 125 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedOneLightTwoBones<10,11> mov oPos.w, r0.x // ::VSSkinnedOneLightTwoBones<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedOneLightTwoBones<3> -#line 129 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 129 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedOneLightTwoBones<8,9> // approximately 57 instruction slots used @@ -205,17 +205,17 @@ ret const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = { - 68, 88, 66, 67, 128, 106, - 85, 102, 37, 42, 216, 89, - 27, 53, 239, 87, 8, 117, - 194, 235, 1, 0, 0, 0, - 252, 19, 0, 0, 4, 0, + 68, 88, 66, 67, 106, 161, + 186, 232, 4, 34, 224, 53, + 143, 224, 192, 138, 69, 159, + 15, 38, 1, 0, 0, 0, + 8, 20, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 224, 11, 0, 0, 176, 18, - 0, 0, 112, 19, 0, 0, - 65, 111, 110, 57, 168, 11, - 0, 0, 168, 11, 0, 0, - 0, 2, 254, 255, 116, 11, + 236, 11, 0, 0, 188, 18, + 0, 0, 124, 19, 0, 0, + 65, 111, 110, 57, 180, 11, + 0, 0, 180, 11, 0, 0, + 0, 2, 254, 255, 128, 11, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -224,14 +224,14 @@ const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 255, 1, 68, 66, 85, 71, + 2, 2, 68, 66, 85, 71, 40, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 55, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 164, 6, 0, 0, - 0, 3, 0, 0, 67, 58, + 0, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -244,7 +244,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -256,7 +256,7 @@ const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -271,79 +271,79 @@ const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 4, 8, + 0, 0, 255, 255, 16, 8, 0, 0, 0, 0, 255, 255, - 28, 8, 0, 0, 0, 0, - 255, 255, 40, 8, 0, 0, - 0, 0, 255, 255, 52, 8, + 40, 8, 0, 0, 0, 0, + 255, 255, 52, 8, 0, 0, + 0, 0, 255, 255, 64, 8, 0, 0, 0, 0, 255, 255, - 64, 8, 0, 0, 0, 0, - 255, 255, 76, 8, 0, 0, - 52, 0, 0, 0, 88, 8, + 76, 8, 0, 0, 0, 0, + 255, 255, 88, 8, 0, 0, + 52, 0, 0, 0, 100, 8, 0, 0, 52, 0, 0, 0, - 104, 8, 0, 0, 52, 0, - 0, 0, 116, 8, 0, 0, - 52, 0, 0, 0, 136, 8, + 116, 8, 0, 0, 52, 0, + 0, 0, 128, 8, 0, 0, + 52, 0, 0, 0, 148, 8, 0, 0, 56, 0, 0, 0, - 160, 8, 0, 0, 55, 0, - 0, 0, 176, 8, 0, 0, - 52, 0, 0, 0, 192, 8, + 172, 8, 0, 0, 55, 0, + 0, 0, 188, 8, 0, 0, + 52, 0, 0, 0, 204, 8, 0, 0, 52, 0, 0, 0, - 212, 8, 0, 0, 52, 0, - 0, 0, 232, 8, 0, 0, - 52, 0, 0, 0, 0, 9, + 224, 8, 0, 0, 52, 0, + 0, 0, 244, 8, 0, 0, + 52, 0, 0, 0, 12, 9, 0, 0, 56, 0, 0, 0, - 24, 9, 0, 0, 55, 0, - 0, 0, 40, 9, 0, 0, - 56, 0, 0, 0, 56, 9, + 36, 9, 0, 0, 55, 0, + 0, 0, 52, 9, 0, 0, + 56, 0, 0, 0, 68, 9, 0, 0, 55, 0, 0, 0, - 72, 9, 0, 0, 59, 0, - 1, 0, 88, 9, 0, 0, - 59, 0, 1, 0, 104, 9, + 84, 9, 0, 0, 59, 0, + 1, 0, 100, 9, 0, 0, + 59, 0, 1, 0, 116, 9, 0, 0, 59, 0, 1, 0, - 120, 9, 0, 0, 59, 0, - 1, 0, 136, 9, 0, 0, - 36, 0, 1, 0, 148, 9, + 132, 9, 0, 0, 59, 0, + 1, 0, 148, 9, 0, 0, + 36, 0, 1, 0, 160, 9, 0, 0, 39, 0, 1, 0, - 164, 9, 0, 0, 41, 0, - 1, 0, 180, 9, 0, 0, - 46, 0, 1, 0, 196, 9, + 176, 9, 0, 0, 41, 0, + 1, 0, 192, 9, 0, 0, + 46, 0, 1, 0, 208, 9, 0, 0, 46, 0, 1, 0, - 212, 9, 0, 0, 46, 0, - 1, 0, 224, 9, 0, 0, - 57, 0, 1, 0, 244, 9, + 224, 9, 0, 0, 46, 0, + 1, 0, 236, 9, 0, 0, + 57, 0, 1, 0, 0, 10, 0, 0, 57, 0, 1, 0, - 0, 10, 0, 0, 57, 0, - 1, 0, 16, 10, 0, 0, - 57, 0, 1, 0, 32, 10, + 12, 10, 0, 0, 57, 0, + 1, 0, 28, 10, 0, 0, + 57, 0, 1, 0, 44, 10, 0, 0, 58, 0, 1, 0, - 48, 10, 0, 0, 58, 0, - 1, 0, 64, 10, 0, 0, - 33, 0, 1, 0, 76, 10, + 60, 10, 0, 0, 58, 0, + 1, 0, 76, 10, 0, 0, + 33, 0, 1, 0, 88, 10, 0, 0, 33, 0, 1, 0, - 92, 10, 0, 0, 37, 0, - 1, 0, 104, 10, 0, 0, - 42, 0, 1, 0, 120, 10, + 104, 10, 0, 0, 37, 0, + 1, 0, 116, 10, 0, 0, + 42, 0, 1, 0, 132, 10, 0, 0, 42, 0, 1, 0, - 136, 10, 0, 0, 42, 0, - 1, 0, 152, 10, 0, 0, - 47, 0, 1, 0, 168, 10, + 148, 10, 0, 0, 42, 0, + 1, 0, 164, 10, 0, 0, + 47, 0, 1, 0, 180, 10, 0, 0, 47, 0, 1, 0, - 184, 10, 0, 0, 63, 0, - 1, 0, 200, 10, 0, 0, - 14, 0, 2, 0, 216, 10, + 196, 10, 0, 0, 63, 0, + 1, 0, 212, 10, 0, 0, + 14, 0, 2, 0, 228, 10, 0, 0, 14, 0, 2, 0, - 232, 10, 0, 0, 14, 0, - 2, 0, 248, 10, 0, 0, - 63, 0, 1, 0, 8, 11, + 244, 10, 0, 0, 14, 0, + 2, 0, 4, 11, 0, 0, + 63, 0, 1, 0, 20, 11, 0, 0, 63, 0, 1, 0, - 24, 11, 0, 0, 63, 0, - 1, 0, 40, 11, 0, 0, - 125, 0, 0, 0, 56, 11, + 36, 11, 0, 0, 63, 0, + 1, 0, 52, 11, 0, 0, + 125, 0, 0, 0, 68, 11, 0, 0, 125, 0, 0, 0, - 76, 11, 0, 0, 46, 0, - 1, 0, 88, 11, 0, 0, - 129, 0, 0, 0, 100, 11, + 88, 11, 0, 0, 46, 0, + 1, 0, 100, 11, 0, 0, + 129, 0, 0, 0, 112, 11, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -564,7 +564,9 @@ const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc index 36a12f39..c3466b47 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc @@ -49,7 +49,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0, v3, c243.x mova a0, r0.yxzw mul r1, v4.y, c26[a0.x] @@ -77,7 +77,7 @@ dp4 r1.z, v0, r3 // Skin::vin<2> dp3 r0.z, v1, r3 // Skin::vin<6> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov r1.w, v0.w dp4 oPos.z, r1, c24 // ::VSSkinnedPixelLightingFourBones<15> dp4 oT1.x, r1, c15 // ::VSSkinnedPixelLightingFourBones<2> @@ -90,17 +90,17 @@ rsq r0.x, r0.x mul oT2.xyz, r0.x, r2 // ::VSSkinnedPixelLightingFourBones<6,7,8> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, r1, c14 max r0.x, r0.x, c243.y min oT1.w, r0.x, c243.z // ::VSSkinnedPixelLightingFourBones<5> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, r1, c22 // ::vout<0> dp4 r0.y, r1, c23 // ::vout<1> dp4 r0.z, r1, c25 // ::vout<3> -#line 191 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 191 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.z, c242, r0 // ::VSSkinnedPixelLightingFourBones<13,14> mov oPos.w, r0.z // ::VSSkinnedPixelLightingFourBones<16> @@ -168,17 +168,17 @@ ret const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = { - 68, 88, 66, 67, 96, 157, - 87, 196, 38, 94, 105, 173, - 51, 47, 110, 253, 0, 184, - 79, 144, 1, 0, 0, 0, - 44, 17, 0, 0, 4, 0, + 68, 88, 66, 67, 163, 175, + 48, 182, 230, 199, 155, 73, + 171, 120, 144, 202, 126, 166, + 78, 168, 1, 0, 0, 0, + 56, 17, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 24, 10, 0, 0, 200, 15, - 0, 0, 136, 16, 0, 0, - 65, 111, 110, 57, 224, 9, - 0, 0, 224, 9, 0, 0, - 0, 2, 254, 255, 172, 9, + 36, 10, 0, 0, 212, 15, + 0, 0, 148, 16, 0, 0, + 65, 111, 110, 57, 236, 9, + 0, 0, 236, 9, 0, 0, + 0, 2, 254, 255, 184, 9, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -187,14 +187,14 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 154, 1, 68, 66, 85, 71, + 157, 1, 68, 66, 85, 71, 40, 0, 0, 0, 60, 6, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 48, 0, 0, 0, 20, 1, 0, 0, 5, 0, 0, 0, 216, 5, 0, 0, - 148, 2, 0, 0, 67, 58, + 148, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -207,7 +207,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -219,7 +219,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -234,70 +234,70 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 112, 6, + 0, 0, 255, 255, 124, 6, 0, 0, 0, 0, 255, 255, - 136, 6, 0, 0, 0, 0, - 255, 255, 148, 6, 0, 0, - 0, 0, 255, 255, 160, 6, + 148, 6, 0, 0, 0, 0, + 255, 255, 160, 6, 0, 0, + 0, 0, 255, 255, 172, 6, 0, 0, 0, 0, 255, 255, - 172, 6, 0, 0, 0, 0, - 255, 255, 184, 6, 0, 0, - 52, 0, 0, 0, 196, 6, + 184, 6, 0, 0, 0, 0, + 255, 255, 196, 6, 0, 0, + 52, 0, 0, 0, 208, 6, 0, 0, 52, 0, 0, 0, - 212, 6, 0, 0, 52, 0, - 0, 0, 224, 6, 0, 0, - 52, 0, 0, 0, 244, 6, + 224, 6, 0, 0, 52, 0, + 0, 0, 236, 6, 0, 0, + 52, 0, 0, 0, 0, 7, 0, 0, 52, 0, 0, 0, - 12, 7, 0, 0, 52, 0, - 0, 0, 36, 7, 0, 0, - 55, 0, 0, 0, 60, 7, + 24, 7, 0, 0, 52, 0, + 0, 0, 48, 7, 0, 0, + 55, 0, 0, 0, 72, 7, 0, 0, 56, 0, 0, 0, - 76, 7, 0, 0, 52, 0, - 0, 0, 92, 7, 0, 0, - 52, 0, 0, 0, 112, 7, + 88, 7, 0, 0, 52, 0, + 0, 0, 104, 7, 0, 0, + 52, 0, 0, 0, 124, 7, 0, 0, 52, 0, 0, 0, - 132, 7, 0, 0, 52, 0, - 0, 0, 156, 7, 0, 0, - 52, 0, 0, 0, 180, 7, + 144, 7, 0, 0, 52, 0, + 0, 0, 168, 7, 0, 0, + 52, 0, 0, 0, 192, 7, 0, 0, 52, 0, 0, 0, - 204, 7, 0, 0, 52, 0, - 0, 0, 228, 7, 0, 0, - 52, 0, 0, 0, 252, 7, + 216, 7, 0, 0, 52, 0, + 0, 0, 240, 7, 0, 0, + 52, 0, 0, 0, 8, 8, 0, 0, 55, 0, 0, 0, - 20, 8, 0, 0, 56, 0, - 0, 0, 36, 8, 0, 0, - 55, 0, 0, 0, 52, 8, + 32, 8, 0, 0, 56, 0, + 0, 0, 48, 8, 0, 0, + 55, 0, 0, 0, 64, 8, 0, 0, 56, 0, 0, 0, - 68, 8, 0, 0, 85, 0, - 1, 0, 84, 8, 0, 0, - 85, 0, 1, 0, 96, 8, + 80, 8, 0, 0, 85, 0, + 1, 0, 96, 8, 0, 0, + 85, 0, 1, 0, 108, 8, 0, 0, 86, 0, 1, 0, - 112, 8, 0, 0, 86, 0, - 1, 0, 128, 8, 0, 0, - 86, 0, 1, 0, 144, 8, + 124, 8, 0, 0, 86, 0, + 1, 0, 140, 8, 0, 0, + 86, 0, 1, 0, 156, 8, 0, 0, 87, 0, 1, 0, - 160, 8, 0, 0, 87, 0, - 1, 0, 176, 8, 0, 0, - 87, 0, 1, 0, 192, 8, + 172, 8, 0, 0, 87, 0, + 1, 0, 188, 8, 0, 0, + 87, 0, 1, 0, 204, 8, 0, 0, 87, 0, 1, 0, - 208, 8, 0, 0, 87, 0, - 1, 0, 224, 8, 0, 0, - 87, 0, 1, 0, 236, 8, + 220, 8, 0, 0, 87, 0, + 1, 0, 236, 8, 0, 0, + 87, 0, 1, 0, 248, 8, 0, 0, 14, 0, 2, 0, - 252, 8, 0, 0, 14, 0, - 2, 0, 12, 9, 0, 0, - 14, 0, 2, 0, 28, 9, + 8, 9, 0, 0, 14, 0, + 2, 0, 24, 9, 0, 0, + 14, 0, 2, 0, 40, 9, 0, 0, 85, 0, 1, 0, - 44, 9, 0, 0, 85, 0, - 1, 0, 60, 9, 0, 0, - 85, 0, 1, 0, 76, 9, + 56, 9, 0, 0, 85, 0, + 1, 0, 72, 9, 0, 0, + 85, 0, 1, 0, 88, 9, 0, 0, 191, 0, 0, 0, - 92, 9, 0, 0, 191, 0, - 0, 0, 112, 9, 0, 0, - 195, 0, 0, 0, 124, 9, + 104, 9, 0, 0, 191, 0, + 0, 0, 124, 9, 0, 0, + 195, 0, 0, 0, 136, 9, 0, 0, 200, 0, 0, 0, - 136, 9, 0, 0, 200, 0, - 0, 0, 148, 9, 0, 0, + 148, 9, 0, 0, 200, 0, + 0, 0, 160, 9, 0, 0, 86, 83, 83, 107, 105, 110, 110, 101, 100, 80, 105, 120, 101, 108, 76, 105, 103, 104, @@ -460,7 +460,9 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 128, 63, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc index a142a541..a0847e4e 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc @@ -49,7 +49,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.x, v3.x, c243.x mova a0.x, r0.x mul r0, v4.x, c26[a0.x] // ::skinning<0,3,6,9> @@ -68,7 +68,7 @@ dp4 r1.z, v0, r3 // Skin::vin<2> dp3 r0.z, v1, r3 // Skin::vin<6> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov r1.w, v0.w dp4 oPos.z, r1, c24 // ::VSSkinnedPixelLightingOneBone<15> dp4 oT1.x, r1, c15 // ::VSSkinnedPixelLightingOneBone<2> @@ -81,17 +81,17 @@ rsq r0.x, r0.x mul oT2.xyz, r0.x, r2 // ::VSSkinnedPixelLightingOneBone<6,7,8> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, r1, c14 max r0.x, r0.x, c243.y min oT1.w, r0.x, c243.z // ::VSSkinnedPixelLightingOneBone<5> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, r1, c22 // ::vout<0> dp4 r0.y, r1, c23 // ::vout<1> dp4 r0.z, r1, c25 // ::vout<3> -#line 157 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 157 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.z, c242, r0 // ::VSSkinnedPixelLightingOneBone<13,14> mov oPos.w, r0.z // ::VSSkinnedPixelLightingOneBone<16> @@ -150,17 +150,17 @@ ret const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = { - 68, 88, 66, 67, 106, 73, - 236, 75, 243, 219, 238, 14, - 117, 141, 149, 254, 34, 55, - 148, 241, 1, 0, 0, 0, - 4, 14, 0, 0, 4, 0, + 68, 88, 66, 67, 109, 107, + 236, 52, 104, 194, 127, 222, + 48, 53, 77, 19, 64, 83, + 52, 124, 1, 0, 0, 0, + 16, 14, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 172, 8, 0, 0, 160, 12, - 0, 0, 96, 13, 0, 0, - 65, 111, 110, 57, 116, 8, - 0, 0, 116, 8, 0, 0, - 0, 2, 254, 255, 64, 8, + 184, 8, 0, 0, 172, 12, + 0, 0, 108, 13, 0, 0, + 65, 111, 110, 57, 128, 8, + 0, 0, 128, 8, 0, 0, + 0, 2, 254, 255, 76, 8, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -169,14 +169,14 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 117, 1, 68, 66, 85, 71, + 120, 1, 68, 66, 85, 71, 40, 0, 0, 0, 168, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 39, 0, 0, 0, 20, 1, 0, 0, 5, 0, 0, 0, 68, 5, 0, 0, - 76, 2, 0, 0, 67, 58, + 76, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -189,7 +189,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -201,7 +201,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -216,58 +216,58 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 220, 5, + 0, 0, 255, 255, 232, 5, 0, 0, 0, 0, 255, 255, - 244, 5, 0, 0, 0, 0, - 255, 255, 0, 6, 0, 0, - 0, 0, 255, 255, 12, 6, + 0, 6, 0, 0, 0, 0, + 255, 255, 12, 6, 0, 0, + 0, 0, 255, 255, 24, 6, 0, 0, 0, 0, 255, 255, - 24, 6, 0, 0, 0, 0, - 255, 255, 36, 6, 0, 0, - 52, 0, 0, 0, 48, 6, + 36, 6, 0, 0, 0, 0, + 255, 255, 48, 6, 0, 0, + 52, 0, 0, 0, 60, 6, 0, 0, 52, 0, 0, 0, - 64, 6, 0, 0, 52, 0, - 0, 0, 76, 6, 0, 0, - 55, 0, 0, 0, 96, 6, + 76, 6, 0, 0, 52, 0, + 0, 0, 88, 6, 0, 0, + 55, 0, 0, 0, 108, 6, 0, 0, 56, 0, 0, 0, - 112, 6, 0, 0, 52, 0, - 0, 0, 128, 6, 0, 0, - 52, 0, 0, 0, 148, 6, + 124, 6, 0, 0, 52, 0, + 0, 0, 140, 6, 0, 0, + 52, 0, 0, 0, 160, 6, 0, 0, 55, 0, 0, 0, - 168, 6, 0, 0, 56, 0, - 0, 0, 184, 6, 0, 0, - 55, 0, 0, 0, 200, 6, + 180, 6, 0, 0, 56, 0, + 0, 0, 196, 6, 0, 0, + 55, 0, 0, 0, 212, 6, 0, 0, 56, 0, 0, 0, - 216, 6, 0, 0, 85, 0, - 1, 0, 232, 6, 0, 0, - 85, 0, 1, 0, 244, 6, + 228, 6, 0, 0, 85, 0, + 1, 0, 244, 6, 0, 0, + 85, 0, 1, 0, 0, 7, 0, 0, 86, 0, 1, 0, - 4, 7, 0, 0, 86, 0, - 1, 0, 20, 7, 0, 0, - 86, 0, 1, 0, 36, 7, + 16, 7, 0, 0, 86, 0, + 1, 0, 32, 7, 0, 0, + 86, 0, 1, 0, 48, 7, 0, 0, 87, 0, 1, 0, - 52, 7, 0, 0, 87, 0, - 1, 0, 68, 7, 0, 0, - 87, 0, 1, 0, 84, 7, + 64, 7, 0, 0, 87, 0, + 1, 0, 80, 7, 0, 0, + 87, 0, 1, 0, 96, 7, 0, 0, 87, 0, 1, 0, - 100, 7, 0, 0, 87, 0, - 1, 0, 116, 7, 0, 0, - 87, 0, 1, 0, 128, 7, + 112, 7, 0, 0, 87, 0, + 1, 0, 128, 7, 0, 0, + 87, 0, 1, 0, 140, 7, 0, 0, 14, 0, 2, 0, - 144, 7, 0, 0, 14, 0, - 2, 0, 160, 7, 0, 0, - 14, 0, 2, 0, 176, 7, + 156, 7, 0, 0, 14, 0, + 2, 0, 172, 7, 0, 0, + 14, 0, 2, 0, 188, 7, 0, 0, 85, 0, 1, 0, - 192, 7, 0, 0, 85, 0, - 1, 0, 208, 7, 0, 0, - 85, 0, 1, 0, 224, 7, + 204, 7, 0, 0, 85, 0, + 1, 0, 220, 7, 0, 0, + 85, 0, 1, 0, 236, 7, 0, 0, 157, 0, 0, 0, - 240, 7, 0, 0, 157, 0, - 0, 0, 4, 8, 0, 0, - 161, 0, 0, 0, 16, 8, + 252, 7, 0, 0, 157, 0, + 0, 0, 16, 8, 0, 0, + 161, 0, 0, 0, 28, 8, 0, 0, 166, 0, 0, 0, - 28, 8, 0, 0, 166, 0, - 0, 0, 40, 8, 0, 0, + 40, 8, 0, 0, 166, 0, + 0, 0, 52, 8, 0, 0, 86, 83, 83, 107, 105, 110, 110, 101, 100, 80, 105, 120, 101, 108, 76, 105, 103, 104, @@ -417,7 +417,9 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc index 326e2883..3319b8ad 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc @@ -49,7 +49,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.xy, v3, c243.x mova a0.xy, r0.yxzw mul r0, v4.y, c26[a0.x] @@ -71,7 +71,7 @@ dp4 r1.z, v0, r3 // Skin::vin<2> dp3 r0.z, v1, r3 // Skin::vin<6> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov r1.w, v0.w dp4 oPos.z, r1, c24 // ::VSSkinnedPixelLightingTwoBones<15> dp4 oT1.x, r1, c15 // ::VSSkinnedPixelLightingTwoBones<2> @@ -84,17 +84,17 @@ rsq r0.x, r0.x mul oT2.xyz, r0.x, r2 // ::VSSkinnedPixelLightingTwoBones<6,7,8> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r0.x, r1, c14 max r0.x, r0.x, c243.y min oT1.w, r0.x, c243.z // ::VSSkinnedPixelLightingTwoBones<5> -#line 85 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 85 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r0.x, r1, c22 // ::vout<0> dp4 r0.y, r1, c23 // ::vout<1> dp4 r0.z, r1, c25 // ::vout<3> -#line 174 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 174 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.z, c242, r0 // ::VSSkinnedPixelLightingTwoBones<13,14> mov oPos.w, r0.z // ::VSSkinnedPixelLightingTwoBones<16> @@ -156,17 +156,17 @@ ret const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = { - 68, 88, 66, 67, 146, 0, - 191, 242, 86, 70, 57, 128, - 104, 67, 87, 60, 45, 136, - 149, 16, 1, 0, 0, 0, - 12, 15, 0, 0, 4, 0, + 68, 88, 66, 67, 194, 20, + 236, 114, 26, 232, 90, 103, + 7, 57, 158, 88, 236, 200, + 233, 23, 1, 0, 0, 0, + 24, 15, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 24, 9, 0, 0, 168, 13, - 0, 0, 104, 14, 0, 0, - 65, 111, 110, 57, 224, 8, - 0, 0, 224, 8, 0, 0, - 0, 2, 254, 255, 172, 8, + 36, 9, 0, 0, 180, 13, + 0, 0, 116, 14, 0, 0, + 65, 111, 110, 57, 236, 8, + 0, 0, 236, 8, 0, 0, + 0, 2, 254, 255, 184, 8, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -175,14 +175,14 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 126, 1, 68, 66, 85, 71, + 129, 1, 68, 66, 85, 71, 40, 0, 0, 0, 204, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 42, 0, 0, 0, 20, 1, 0, 0, 5, 0, 0, 0, 104, 5, 0, 0, - 100, 2, 0, 0, 67, 58, + 100, 2, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -195,7 +195,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -207,7 +207,7 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -222,62 +222,62 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 0, 6, + 0, 0, 255, 255, 12, 6, 0, 0, 0, 0, 255, 255, - 24, 6, 0, 0, 0, 0, - 255, 255, 36, 6, 0, 0, - 0, 0, 255, 255, 48, 6, + 36, 6, 0, 0, 0, 0, + 255, 255, 48, 6, 0, 0, + 0, 0, 255, 255, 60, 6, 0, 0, 0, 0, 255, 255, - 60, 6, 0, 0, 0, 0, - 255, 255, 72, 6, 0, 0, - 52, 0, 0, 0, 84, 6, + 72, 6, 0, 0, 0, 0, + 255, 255, 84, 6, 0, 0, + 52, 0, 0, 0, 96, 6, 0, 0, 52, 0, 0, 0, - 100, 6, 0, 0, 52, 0, - 0, 0, 112, 6, 0, 0, - 52, 0, 0, 0, 132, 6, + 112, 6, 0, 0, 52, 0, + 0, 0, 124, 6, 0, 0, + 52, 0, 0, 0, 144, 6, 0, 0, 55, 0, 0, 0, - 156, 6, 0, 0, 56, 0, - 0, 0, 172, 6, 0, 0, - 52, 0, 0, 0, 188, 6, + 168, 6, 0, 0, 56, 0, + 0, 0, 184, 6, 0, 0, + 52, 0, 0, 0, 200, 6, 0, 0, 52, 0, 0, 0, - 208, 6, 0, 0, 52, 0, - 0, 0, 228, 6, 0, 0, - 52, 0, 0, 0, 252, 6, + 220, 6, 0, 0, 52, 0, + 0, 0, 240, 6, 0, 0, + 52, 0, 0, 0, 8, 7, 0, 0, 55, 0, 0, 0, - 20, 7, 0, 0, 56, 0, - 0, 0, 36, 7, 0, 0, - 55, 0, 0, 0, 52, 7, + 32, 7, 0, 0, 56, 0, + 0, 0, 48, 7, 0, 0, + 55, 0, 0, 0, 64, 7, 0, 0, 56, 0, 0, 0, - 68, 7, 0, 0, 85, 0, - 1, 0, 84, 7, 0, 0, - 85, 0, 1, 0, 96, 7, + 80, 7, 0, 0, 85, 0, + 1, 0, 96, 7, 0, 0, + 85, 0, 1, 0, 108, 7, 0, 0, 86, 0, 1, 0, - 112, 7, 0, 0, 86, 0, - 1, 0, 128, 7, 0, 0, - 86, 0, 1, 0, 144, 7, + 124, 7, 0, 0, 86, 0, + 1, 0, 140, 7, 0, 0, + 86, 0, 1, 0, 156, 7, 0, 0, 87, 0, 1, 0, - 160, 7, 0, 0, 87, 0, - 1, 0, 176, 7, 0, 0, - 87, 0, 1, 0, 192, 7, + 172, 7, 0, 0, 87, 0, + 1, 0, 188, 7, 0, 0, + 87, 0, 1, 0, 204, 7, 0, 0, 87, 0, 1, 0, - 208, 7, 0, 0, 87, 0, - 1, 0, 224, 7, 0, 0, - 87, 0, 1, 0, 236, 7, + 220, 7, 0, 0, 87, 0, + 1, 0, 236, 7, 0, 0, + 87, 0, 1, 0, 248, 7, 0, 0, 14, 0, 2, 0, - 252, 7, 0, 0, 14, 0, - 2, 0, 12, 8, 0, 0, - 14, 0, 2, 0, 28, 8, + 8, 8, 0, 0, 14, 0, + 2, 0, 24, 8, 0, 0, + 14, 0, 2, 0, 40, 8, 0, 0, 85, 0, 1, 0, - 44, 8, 0, 0, 85, 0, - 1, 0, 60, 8, 0, 0, - 85, 0, 1, 0, 76, 8, + 56, 8, 0, 0, 85, 0, + 1, 0, 72, 8, 0, 0, + 85, 0, 1, 0, 88, 8, 0, 0, 174, 0, 0, 0, - 92, 8, 0, 0, 174, 0, - 0, 0, 112, 8, 0, 0, - 178, 0, 0, 0, 124, 8, + 104, 8, 0, 0, 174, 0, + 0, 0, 124, 8, 0, 0, + 178, 0, 0, 0, 136, 8, 0, 0, 183, 0, 0, 0, - 136, 8, 0, 0, 183, 0, - 0, 0, 148, 8, 0, 0, + 148, 8, 0, 0, 183, 0, + 0, 0, 160, 8, 0, 0, 86, 83, 83, 107, 105, 110, 110, 101, 100, 80, 105, 120, 101, 108, 76, 105, 103, 104, @@ -429,7 +429,9 @@ const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 49, 48, 46, 49, 0, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc index 047d5980..b813e67b 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0, v3, c243.x mova a0, r0.yxzw mul r1, v4.y, c26[a0.x] @@ -76,7 +76,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -151,24 +151,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedVertexLightingFourBones<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedVertexLightingFourBones<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 93 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 93 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedVertexLightingFourBones<10,11> mov oPos.w, r0.x // ::VSSkinnedVertexLightingFourBones<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedVertexLightingFourBones<3> -#line 97 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 97 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedVertexLightingFourBones<8,9> // approximately 83 instruction slots used @@ -263,17 +263,17 @@ ret const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = { - 68, 88, 66, 67, 51, 115, - 67, 123, 215, 206, 157, 189, - 141, 71, 169, 45, 88, 67, - 184, 117, 1, 0, 0, 0, - 96, 26, 0, 0, 4, 0, + 68, 88, 66, 67, 36, 157, + 87, 113, 150, 21, 250, 23, + 26, 109, 79, 97, 4, 88, + 28, 186, 1, 0, 0, 0, + 108, 26, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 240, 14, 0, 0, 20, 25, - 0, 0, 212, 25, 0, 0, - 65, 111, 110, 57, 184, 14, - 0, 0, 184, 14, 0, 0, - 0, 2, 254, 255, 132, 14, + 252, 14, 0, 0, 32, 25, + 0, 0, 224, 25, 0, 0, + 65, 111, 110, 57, 196, 14, + 0, 0, 196, 14, 0, 0, + 0, 2, 254, 255, 144, 14, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -282,14 +282,14 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 91, 2, 68, 66, 85, 71, + 94, 2, 68, 66, 85, 71, 40, 0, 0, 0, 64, 9, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 79, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 20, 8, 0, 0, - 192, 3, 0, 0, 67, 58, + 192, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -302,7 +302,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -314,7 +314,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -329,111 +329,111 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 116, 9, + 0, 0, 255, 255, 128, 9, 0, 0, 0, 0, 255, 255, - 140, 9, 0, 0, 0, 0, - 255, 255, 152, 9, 0, 0, - 0, 0, 255, 255, 164, 9, + 152, 9, 0, 0, 0, 0, + 255, 255, 164, 9, 0, 0, + 0, 0, 255, 255, 176, 9, 0, 0, 0, 0, 255, 255, - 176, 9, 0, 0, 0, 0, - 255, 255, 188, 9, 0, 0, - 52, 0, 0, 0, 200, 9, + 188, 9, 0, 0, 0, 0, + 255, 255, 200, 9, 0, 0, + 52, 0, 0, 0, 212, 9, 0, 0, 52, 0, 0, 0, - 216, 9, 0, 0, 52, 0, - 0, 0, 228, 9, 0, 0, - 52, 0, 0, 0, 248, 9, + 228, 9, 0, 0, 52, 0, + 0, 0, 240, 9, 0, 0, + 52, 0, 0, 0, 4, 10, 0, 0, 52, 0, 0, 0, - 16, 10, 0, 0, 52, 0, - 0, 0, 40, 10, 0, 0, - 56, 0, 0, 0, 64, 10, + 28, 10, 0, 0, 52, 0, + 0, 0, 52, 10, 0, 0, + 56, 0, 0, 0, 76, 10, 0, 0, 55, 0, 0, 0, - 80, 10, 0, 0, 52, 0, - 0, 0, 96, 10, 0, 0, - 52, 0, 0, 0, 116, 10, + 92, 10, 0, 0, 52, 0, + 0, 0, 108, 10, 0, 0, + 52, 0, 0, 0, 128, 10, 0, 0, 52, 0, 0, 0, - 136, 10, 0, 0, 52, 0, - 0, 0, 160, 10, 0, 0, - 52, 0, 0, 0, 184, 10, + 148, 10, 0, 0, 52, 0, + 0, 0, 172, 10, 0, 0, + 52, 0, 0, 0, 196, 10, 0, 0, 52, 0, 0, 0, - 208, 10, 0, 0, 52, 0, - 0, 0, 232, 10, 0, 0, - 52, 0, 0, 0, 0, 11, + 220, 10, 0, 0, 52, 0, + 0, 0, 244, 10, 0, 0, + 52, 0, 0, 0, 12, 11, 0, 0, 56, 0, 0, 0, - 24, 11, 0, 0, 55, 0, - 0, 0, 40, 11, 0, 0, - 56, 0, 0, 0, 56, 11, + 36, 11, 0, 0, 55, 0, + 0, 0, 52, 11, 0, 0, + 56, 0, 0, 0, 68, 11, 0, 0, 55, 0, 0, 0, - 72, 11, 0, 0, 59, 0, - 1, 0, 88, 11, 0, 0, - 59, 0, 1, 0, 104, 11, + 84, 11, 0, 0, 59, 0, + 1, 0, 100, 11, 0, 0, + 59, 0, 1, 0, 116, 11, 0, 0, 59, 0, 1, 0, - 120, 11, 0, 0, 59, 0, - 1, 0, 136, 11, 0, 0, - 36, 0, 1, 0, 148, 11, + 132, 11, 0, 0, 59, 0, + 1, 0, 148, 11, 0, 0, + 36, 0, 1, 0, 160, 11, 0, 0, 36, 0, 1, 0, - 164, 11, 0, 0, 36, 0, - 1, 0, 180, 11, 0, 0, - 39, 0, 1, 0, 196, 11, + 176, 11, 0, 0, 36, 0, + 1, 0, 192, 11, 0, 0, + 39, 0, 1, 0, 208, 11, 0, 0, 41, 0, 1, 0, - 212, 11, 0, 0, 46, 0, - 1, 0, 228, 11, 0, 0, - 46, 0, 1, 0, 244, 11, + 224, 11, 0, 0, 46, 0, + 1, 0, 240, 11, 0, 0, + 46, 0, 1, 0, 0, 12, 0, 0, 46, 0, 1, 0, - 8, 12, 0, 0, 46, 0, - 1, 0, 28, 12, 0, 0, - 46, 0, 1, 0, 40, 12, + 20, 12, 0, 0, 46, 0, + 1, 0, 40, 12, 0, 0, + 46, 0, 1, 0, 52, 12, 0, 0, 57, 0, 1, 0, - 60, 12, 0, 0, 57, 0, - 1, 0, 72, 12, 0, 0, - 57, 0, 1, 0, 88, 12, + 72, 12, 0, 0, 57, 0, + 1, 0, 84, 12, 0, 0, + 57, 0, 1, 0, 100, 12, 0, 0, 57, 0, 1, 0, - 104, 12, 0, 0, 58, 0, - 1, 0, 120, 12, 0, 0, - 58, 0, 1, 0, 136, 12, + 116, 12, 0, 0, 58, 0, + 1, 0, 132, 12, 0, 0, + 58, 0, 1, 0, 148, 12, 0, 0, 33, 0, 1, 0, - 148, 12, 0, 0, 33, 0, - 1, 0, 164, 12, 0, 0, - 37, 0, 1, 0, 176, 12, + 160, 12, 0, 0, 33, 0, + 1, 0, 176, 12, 0, 0, + 37, 0, 1, 0, 188, 12, 0, 0, 33, 0, 1, 0, - 192, 12, 0, 0, 33, 0, - 1, 0, 208, 12, 0, 0, - 33, 0, 1, 0, 224, 12, + 204, 12, 0, 0, 33, 0, + 1, 0, 220, 12, 0, 0, + 33, 0, 1, 0, 236, 12, 0, 0, 37, 0, 1, 0, - 236, 12, 0, 0, 33, 0, - 1, 0, 252, 12, 0, 0, - 37, 0, 1, 0, 8, 13, + 248, 12, 0, 0, 33, 0, + 1, 0, 8, 13, 0, 0, + 37, 0, 1, 0, 20, 13, 0, 0, 42, 0, 1, 0, - 24, 13, 0, 0, 42, 0, - 1, 0, 40, 13, 0, 0, - 42, 0, 1, 0, 56, 13, + 36, 13, 0, 0, 42, 0, + 1, 0, 52, 13, 0, 0, + 42, 0, 1, 0, 68, 13, 0, 0, 42, 0, 1, 0, - 68, 13, 0, 0, 42, 0, - 1, 0, 80, 13, 0, 0, - 42, 0, 1, 0, 92, 13, + 80, 13, 0, 0, 42, 0, + 1, 0, 92, 13, 0, 0, + 42, 0, 1, 0, 104, 13, 0, 0, 42, 0, 1, 0, - 108, 13, 0, 0, 47, 0, - 1, 0, 120, 13, 0, 0, - 42, 0, 1, 0, 136, 13, + 120, 13, 0, 0, 47, 0, + 1, 0, 132, 13, 0, 0, + 42, 0, 1, 0, 148, 13, 0, 0, 42, 0, 1, 0, - 148, 13, 0, 0, 47, 0, - 1, 0, 160, 13, 0, 0, - 47, 0, 1, 0, 180, 13, + 160, 13, 0, 0, 47, 0, + 1, 0, 172, 13, 0, 0, + 47, 0, 1, 0, 192, 13, 0, 0, 47, 0, 1, 0, - 200, 13, 0, 0, 63, 0, - 1, 0, 216, 13, 0, 0, - 14, 0, 2, 0, 232, 13, + 212, 13, 0, 0, 63, 0, + 1, 0, 228, 13, 0, 0, + 14, 0, 2, 0, 244, 13, 0, 0, 14, 0, 2, 0, - 248, 13, 0, 0, 14, 0, - 2, 0, 8, 14, 0, 0, - 63, 0, 1, 0, 24, 14, + 4, 14, 0, 0, 14, 0, + 2, 0, 20, 14, 0, 0, + 63, 0, 1, 0, 36, 14, 0, 0, 63, 0, 1, 0, - 40, 14, 0, 0, 63, 0, - 1, 0, 56, 14, 0, 0, - 93, 0, 0, 0, 72, 14, + 52, 14, 0, 0, 63, 0, + 1, 0, 68, 14, 0, 0, + 93, 0, 0, 0, 84, 14, 0, 0, 93, 0, 0, 0, - 92, 14, 0, 0, 46, 0, - 1, 0, 104, 14, 0, 0, - 97, 0, 0, 0, 116, 14, + 104, 14, 0, 0, 46, 0, + 1, 0, 116, 14, 0, 0, + 97, 0, 0, 0, 128, 14, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -684,7 +684,9 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 81, 0, 0, 5, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc index 146f175a..09850bf5 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.x, v3.x, c243.x mova a0.x, r0.x mul r0, v4.x, c26[a0.x] // ::skinning<0,3,6,9> @@ -67,7 +67,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -142,24 +142,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedVertexLightingOneBone<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedVertexLightingOneBone<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 61 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 61 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedVertexLightingOneBone<10,11> mov oPos.w, r0.x // ::VSSkinnedVertexLightingOneBone<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedVertexLightingOneBone<3> -#line 65 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 65 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedVertexLightingOneBone<8,9> // approximately 74 instruction slots used @@ -245,17 +245,17 @@ ret const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = { - 68, 88, 66, 67, 138, 131, - 143, 200, 165, 140, 158, 241, - 96, 249, 47, 18, 4, 71, - 218, 185, 1, 0, 0, 0, - 56, 23, 0, 0, 4, 0, + 68, 88, 66, 67, 121, 255, + 0, 202, 130, 28, 228, 143, + 40, 196, 216, 143, 88, 87, + 129, 23, 1, 0, 0, 0, + 68, 23, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 132, 13, 0, 0, 236, 21, - 0, 0, 172, 22, 0, 0, - 65, 111, 110, 57, 76, 13, - 0, 0, 76, 13, 0, 0, - 0, 2, 254, 255, 24, 13, + 144, 13, 0, 0, 248, 21, + 0, 0, 184, 22, 0, 0, + 65, 111, 110, 57, 88, 13, + 0, 0, 88, 13, 0, 0, + 0, 2, 254, 255, 36, 13, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -264,14 +264,14 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 54, 2, 68, 66, 85, 71, + 57, 2, 68, 66, 85, 71, 40, 0, 0, 0, 172, 8, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 70, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 128, 7, 0, 0, - 120, 3, 0, 0, 67, 58, + 120, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -284,7 +284,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -296,7 +296,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -311,99 +311,99 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 224, 8, + 0, 0, 255, 255, 236, 8, 0, 0, 0, 0, 255, 255, - 248, 8, 0, 0, 0, 0, - 255, 255, 4, 9, 0, 0, - 0, 0, 255, 255, 16, 9, + 4, 9, 0, 0, 0, 0, + 255, 255, 16, 9, 0, 0, + 0, 0, 255, 255, 28, 9, 0, 0, 0, 0, 255, 255, - 28, 9, 0, 0, 0, 0, - 255, 255, 40, 9, 0, 0, - 52, 0, 0, 0, 52, 9, + 40, 9, 0, 0, 0, 0, + 255, 255, 52, 9, 0, 0, + 52, 0, 0, 0, 64, 9, 0, 0, 52, 0, 0, 0, - 68, 9, 0, 0, 52, 0, - 0, 0, 80, 9, 0, 0, - 56, 0, 0, 0, 100, 9, + 80, 9, 0, 0, 52, 0, + 0, 0, 92, 9, 0, 0, + 56, 0, 0, 0, 112, 9, 0, 0, 55, 0, 0, 0, - 116, 9, 0, 0, 52, 0, - 0, 0, 132, 9, 0, 0, - 52, 0, 0, 0, 152, 9, + 128, 9, 0, 0, 52, 0, + 0, 0, 144, 9, 0, 0, + 52, 0, 0, 0, 164, 9, 0, 0, 56, 0, 0, 0, - 172, 9, 0, 0, 55, 0, - 0, 0, 188, 9, 0, 0, - 56, 0, 0, 0, 204, 9, + 184, 9, 0, 0, 55, 0, + 0, 0, 200, 9, 0, 0, + 56, 0, 0, 0, 216, 9, 0, 0, 55, 0, 0, 0, - 220, 9, 0, 0, 59, 0, - 1, 0, 236, 9, 0, 0, - 59, 0, 1, 0, 252, 9, + 232, 9, 0, 0, 59, 0, + 1, 0, 248, 9, 0, 0, + 59, 0, 1, 0, 8, 10, 0, 0, 59, 0, 1, 0, - 12, 10, 0, 0, 59, 0, - 1, 0, 28, 10, 0, 0, - 36, 0, 1, 0, 40, 10, + 24, 10, 0, 0, 59, 0, + 1, 0, 40, 10, 0, 0, + 36, 0, 1, 0, 52, 10, 0, 0, 36, 0, 1, 0, - 56, 10, 0, 0, 36, 0, - 1, 0, 72, 10, 0, 0, - 39, 0, 1, 0, 88, 10, + 68, 10, 0, 0, 36, 0, + 1, 0, 84, 10, 0, 0, + 39, 0, 1, 0, 100, 10, 0, 0, 41, 0, 1, 0, - 104, 10, 0, 0, 46, 0, - 1, 0, 120, 10, 0, 0, - 46, 0, 1, 0, 136, 10, + 116, 10, 0, 0, 46, 0, + 1, 0, 132, 10, 0, 0, + 46, 0, 1, 0, 148, 10, 0, 0, 46, 0, 1, 0, - 156, 10, 0, 0, 46, 0, - 1, 0, 176, 10, 0, 0, - 46, 0, 1, 0, 188, 10, + 168, 10, 0, 0, 46, 0, + 1, 0, 188, 10, 0, 0, + 46, 0, 1, 0, 200, 10, 0, 0, 57, 0, 1, 0, - 208, 10, 0, 0, 57, 0, - 1, 0, 220, 10, 0, 0, - 57, 0, 1, 0, 236, 10, + 220, 10, 0, 0, 57, 0, + 1, 0, 232, 10, 0, 0, + 57, 0, 1, 0, 248, 10, 0, 0, 57, 0, 1, 0, - 252, 10, 0, 0, 58, 0, - 1, 0, 12, 11, 0, 0, - 58, 0, 1, 0, 28, 11, + 8, 11, 0, 0, 58, 0, + 1, 0, 24, 11, 0, 0, + 58, 0, 1, 0, 40, 11, 0, 0, 33, 0, 1, 0, - 40, 11, 0, 0, 33, 0, - 1, 0, 56, 11, 0, 0, - 37, 0, 1, 0, 68, 11, + 52, 11, 0, 0, 33, 0, + 1, 0, 68, 11, 0, 0, + 37, 0, 1, 0, 80, 11, 0, 0, 33, 0, 1, 0, - 84, 11, 0, 0, 33, 0, - 1, 0, 100, 11, 0, 0, - 33, 0, 1, 0, 116, 11, + 96, 11, 0, 0, 33, 0, + 1, 0, 112, 11, 0, 0, + 33, 0, 1, 0, 128, 11, 0, 0, 37, 0, 1, 0, - 128, 11, 0, 0, 33, 0, - 1, 0, 144, 11, 0, 0, - 37, 0, 1, 0, 156, 11, + 140, 11, 0, 0, 33, 0, + 1, 0, 156, 11, 0, 0, + 37, 0, 1, 0, 168, 11, 0, 0, 42, 0, 1, 0, - 172, 11, 0, 0, 42, 0, - 1, 0, 188, 11, 0, 0, - 42, 0, 1, 0, 204, 11, + 184, 11, 0, 0, 42, 0, + 1, 0, 200, 11, 0, 0, + 42, 0, 1, 0, 216, 11, 0, 0, 42, 0, 1, 0, - 216, 11, 0, 0, 42, 0, - 1, 0, 228, 11, 0, 0, - 42, 0, 1, 0, 240, 11, + 228, 11, 0, 0, 42, 0, + 1, 0, 240, 11, 0, 0, + 42, 0, 1, 0, 252, 11, 0, 0, 42, 0, 1, 0, - 0, 12, 0, 0, 47, 0, - 1, 0, 12, 12, 0, 0, - 42, 0, 1, 0, 28, 12, + 12, 12, 0, 0, 47, 0, + 1, 0, 24, 12, 0, 0, + 42, 0, 1, 0, 40, 12, 0, 0, 42, 0, 1, 0, - 40, 12, 0, 0, 47, 0, - 1, 0, 52, 12, 0, 0, - 47, 0, 1, 0, 72, 12, + 52, 12, 0, 0, 47, 0, + 1, 0, 64, 12, 0, 0, + 47, 0, 1, 0, 84, 12, 0, 0, 47, 0, 1, 0, - 92, 12, 0, 0, 63, 0, - 1, 0, 108, 12, 0, 0, - 14, 0, 2, 0, 124, 12, + 104, 12, 0, 0, 63, 0, + 1, 0, 120, 12, 0, 0, + 14, 0, 2, 0, 136, 12, 0, 0, 14, 0, 2, 0, - 140, 12, 0, 0, 14, 0, - 2, 0, 156, 12, 0, 0, - 63, 0, 1, 0, 172, 12, + 152, 12, 0, 0, 14, 0, + 2, 0, 168, 12, 0, 0, + 63, 0, 1, 0, 184, 12, 0, 0, 63, 0, 1, 0, - 188, 12, 0, 0, 63, 0, - 1, 0, 204, 12, 0, 0, - 61, 0, 0, 0, 220, 12, + 200, 12, 0, 0, 63, 0, + 1, 0, 216, 12, 0, 0, + 61, 0, 0, 0, 232, 12, 0, 0, 61, 0, 0, 0, - 240, 12, 0, 0, 46, 0, - 1, 0, 252, 12, 0, 0, - 65, 0, 0, 0, 8, 13, + 252, 12, 0, 0, 46, 0, + 1, 0, 8, 13, 0, 0, + 65, 0, 0, 0, 20, 13, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -641,7 +641,9 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 128, 63, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc index 6006b6ea..9c4dd2b4 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc @@ -48,7 +48,7 @@ dcl_texcoord3 v3 // vin<9,10,11,12> dcl_texcoord4 v4 // vin<13,14,15,16> -#line 52 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 52 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mul r0.xy, v3, c243.x mova a0.xy, r0.yxzw mul r0, v4.y, c26[a0.x] @@ -70,7 +70,7 @@ dp3 r1.z, v1, r3 // Skin::vin<6> dp4 r0.z, v0, r3 // Skin::vin<2> -#line 59 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 59 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp3 r2.x, r1, c19 dp3 r2.y, r1, c20 dp3 r2.z, r1, c21 @@ -145,24 +145,24 @@ #line 63 dp4 oPos.z, r0, c24 // ::VSSkinnedVertexLightingTwoBones<12> -#line 14 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" +#line 14 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Common.fxh" dp4 r1.x, r0, c14 max r1.x, r1.x, c243.y min oT1.w, r1.x, c243.z // ::VSSkinnedVertexLightingTwoBones<7> -#line 63 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 63 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" dp4 r1.x, r0, c22 // ::vout<0> dp4 r1.y, r0, c23 // ::vout<1> dp4 r0.x, r0, c25 // ::vout<3> -#line 77 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 77 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mad oPos.xy, r0.x, c242, r1 // ::VSSkinnedVertexLightingTwoBones<10,11> mov oPos.w, r0.x // ::VSSkinnedVertexLightingTwoBones<13> -#line 46 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" +#line 46 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\Lighting.fxh" mov oT0.w, c0.w // ::VSSkinnedVertexLightingTwoBones<3> -#line 81 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" +#line 81 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SkinnedEffect.fx" mov oT2.xy, v2 // ::VSSkinnedVertexLightingTwoBones<8,9> // approximately 77 instruction slots used @@ -251,17 +251,17 @@ ret const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = { - 68, 88, 66, 67, 212, 21, - 13, 85, 47, 58, 239, 39, - 103, 86, 186, 79, 72, 239, - 197, 76, 1, 0, 0, 0, - 52, 24, 0, 0, 4, 0, + 68, 88, 66, 67, 121, 215, + 18, 71, 171, 4, 63, 79, + 115, 157, 2, 131, 233, 40, + 137, 247, 1, 0, 0, 0, + 64, 24, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 228, 13, 0, 0, 232, 22, - 0, 0, 168, 23, 0, 0, - 65, 111, 110, 57, 172, 13, - 0, 0, 172, 13, 0, 0, - 0, 2, 254, 255, 120, 13, + 240, 13, 0, 0, 244, 22, + 0, 0, 180, 23, 0, 0, + 65, 111, 110, 57, 184, 13, + 0, 0, 184, 13, 0, 0, + 0, 2, 254, 255, 132, 13, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -270,14 +270,14 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 2, 254, 255, 254, 255, - 60, 2, 68, 66, 85, 71, + 63, 2, 68, 66, 85, 71, 40, 0, 0, 0, 196, 8, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 8, 1, 0, 0, 73, 0, 0, 0, 20, 1, 0, 0, 15, 0, 0, 0, 152, 7, 0, 0, - 144, 3, 0, 0, 67, 58, + 144, 3, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -290,7 +290,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = 101, 114, 115, 92, 83, 107, 105, 110, 110, 101, 100, 69, 102, 102, 101, 99, 116, 46, - 102, 120, 0, 67, 58, 92, + 102, 120, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, 112, @@ -302,7 +302,7 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = 92, 83, 104, 97, 100, 101, 114, 115, 92, 76, 105, 103, 104, 116, 105, 110, 103, 46, - 102, 120, 104, 0, 67, 58, + 102, 120, 104, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -317,103 +317,103 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = 120, 104, 0, 171, 171, 171, 40, 0, 0, 0, 117, 0, 0, 0, 190, 0, 0, 0, - 0, 0, 255, 255, 248, 8, + 0, 0, 255, 255, 4, 9, 0, 0, 0, 0, 255, 255, - 16, 9, 0, 0, 0, 0, - 255, 255, 28, 9, 0, 0, - 0, 0, 255, 255, 40, 9, + 28, 9, 0, 0, 0, 0, + 255, 255, 40, 9, 0, 0, + 0, 0, 255, 255, 52, 9, 0, 0, 0, 0, 255, 255, - 52, 9, 0, 0, 0, 0, - 255, 255, 64, 9, 0, 0, - 52, 0, 0, 0, 76, 9, + 64, 9, 0, 0, 0, 0, + 255, 255, 76, 9, 0, 0, + 52, 0, 0, 0, 88, 9, 0, 0, 52, 0, 0, 0, - 92, 9, 0, 0, 52, 0, - 0, 0, 104, 9, 0, 0, - 52, 0, 0, 0, 124, 9, + 104, 9, 0, 0, 52, 0, + 0, 0, 116, 9, 0, 0, + 52, 0, 0, 0, 136, 9, 0, 0, 56, 0, 0, 0, - 148, 9, 0, 0, 55, 0, - 0, 0, 164, 9, 0, 0, - 52, 0, 0, 0, 180, 9, + 160, 9, 0, 0, 55, 0, + 0, 0, 176, 9, 0, 0, + 52, 0, 0, 0, 192, 9, 0, 0, 52, 0, 0, 0, - 200, 9, 0, 0, 52, 0, - 0, 0, 220, 9, 0, 0, - 52, 0, 0, 0, 244, 9, + 212, 9, 0, 0, 52, 0, + 0, 0, 232, 9, 0, 0, + 52, 0, 0, 0, 0, 10, 0, 0, 56, 0, 0, 0, - 12, 10, 0, 0, 55, 0, - 0, 0, 28, 10, 0, 0, - 56, 0, 0, 0, 44, 10, + 24, 10, 0, 0, 55, 0, + 0, 0, 40, 10, 0, 0, + 56, 0, 0, 0, 56, 10, 0, 0, 55, 0, 0, 0, - 60, 10, 0, 0, 59, 0, - 1, 0, 76, 10, 0, 0, - 59, 0, 1, 0, 92, 10, + 72, 10, 0, 0, 59, 0, + 1, 0, 88, 10, 0, 0, + 59, 0, 1, 0, 104, 10, 0, 0, 59, 0, 1, 0, - 108, 10, 0, 0, 59, 0, - 1, 0, 124, 10, 0, 0, - 36, 0, 1, 0, 136, 10, + 120, 10, 0, 0, 59, 0, + 1, 0, 136, 10, 0, 0, + 36, 0, 1, 0, 148, 10, 0, 0, 36, 0, 1, 0, - 152, 10, 0, 0, 36, 0, - 1, 0, 168, 10, 0, 0, - 39, 0, 1, 0, 184, 10, + 164, 10, 0, 0, 36, 0, + 1, 0, 180, 10, 0, 0, + 39, 0, 1, 0, 196, 10, 0, 0, 41, 0, 1, 0, - 200, 10, 0, 0, 46, 0, - 1, 0, 216, 10, 0, 0, - 46, 0, 1, 0, 232, 10, + 212, 10, 0, 0, 46, 0, + 1, 0, 228, 10, 0, 0, + 46, 0, 1, 0, 244, 10, 0, 0, 46, 0, 1, 0, - 252, 10, 0, 0, 46, 0, - 1, 0, 16, 11, 0, 0, - 46, 0, 1, 0, 28, 11, + 8, 11, 0, 0, 46, 0, + 1, 0, 28, 11, 0, 0, + 46, 0, 1, 0, 40, 11, 0, 0, 57, 0, 1, 0, - 48, 11, 0, 0, 57, 0, - 1, 0, 60, 11, 0, 0, - 57, 0, 1, 0, 76, 11, + 60, 11, 0, 0, 57, 0, + 1, 0, 72, 11, 0, 0, + 57, 0, 1, 0, 88, 11, 0, 0, 57, 0, 1, 0, - 92, 11, 0, 0, 58, 0, - 1, 0, 108, 11, 0, 0, - 58, 0, 1, 0, 124, 11, + 104, 11, 0, 0, 58, 0, + 1, 0, 120, 11, 0, 0, + 58, 0, 1, 0, 136, 11, 0, 0, 33, 0, 1, 0, - 136, 11, 0, 0, 33, 0, - 1, 0, 152, 11, 0, 0, - 37, 0, 1, 0, 164, 11, + 148, 11, 0, 0, 33, 0, + 1, 0, 164, 11, 0, 0, + 37, 0, 1, 0, 176, 11, 0, 0, 33, 0, 1, 0, - 180, 11, 0, 0, 33, 0, - 1, 0, 196, 11, 0, 0, - 33, 0, 1, 0, 212, 11, + 192, 11, 0, 0, 33, 0, + 1, 0, 208, 11, 0, 0, + 33, 0, 1, 0, 224, 11, 0, 0, 37, 0, 1, 0, - 224, 11, 0, 0, 33, 0, - 1, 0, 240, 11, 0, 0, - 37, 0, 1, 0, 252, 11, + 236, 11, 0, 0, 33, 0, + 1, 0, 252, 11, 0, 0, + 37, 0, 1, 0, 8, 12, 0, 0, 42, 0, 1, 0, - 12, 12, 0, 0, 42, 0, - 1, 0, 28, 12, 0, 0, - 42, 0, 1, 0, 44, 12, + 24, 12, 0, 0, 42, 0, + 1, 0, 40, 12, 0, 0, + 42, 0, 1, 0, 56, 12, 0, 0, 42, 0, 1, 0, - 56, 12, 0, 0, 42, 0, - 1, 0, 68, 12, 0, 0, - 42, 0, 1, 0, 80, 12, + 68, 12, 0, 0, 42, 0, + 1, 0, 80, 12, 0, 0, + 42, 0, 1, 0, 92, 12, 0, 0, 42, 0, 1, 0, - 96, 12, 0, 0, 47, 0, - 1, 0, 108, 12, 0, 0, - 42, 0, 1, 0, 124, 12, + 108, 12, 0, 0, 47, 0, + 1, 0, 120, 12, 0, 0, + 42, 0, 1, 0, 136, 12, 0, 0, 42, 0, 1, 0, - 136, 12, 0, 0, 47, 0, - 1, 0, 148, 12, 0, 0, - 47, 0, 1, 0, 168, 12, + 148, 12, 0, 0, 47, 0, + 1, 0, 160, 12, 0, 0, + 47, 0, 1, 0, 180, 12, 0, 0, 47, 0, 1, 0, - 188, 12, 0, 0, 63, 0, - 1, 0, 204, 12, 0, 0, - 14, 0, 2, 0, 220, 12, + 200, 12, 0, 0, 63, 0, + 1, 0, 216, 12, 0, 0, + 14, 0, 2, 0, 232, 12, 0, 0, 14, 0, 2, 0, - 236, 12, 0, 0, 14, 0, - 2, 0, 252, 12, 0, 0, - 63, 0, 1, 0, 12, 13, + 248, 12, 0, 0, 14, 0, + 2, 0, 8, 13, 0, 0, + 63, 0, 1, 0, 24, 13, 0, 0, 63, 0, 1, 0, - 28, 13, 0, 0, 63, 0, - 1, 0, 44, 13, 0, 0, - 77, 0, 0, 0, 60, 13, + 40, 13, 0, 0, 63, 0, + 1, 0, 56, 13, 0, 0, + 77, 0, 0, 0, 72, 13, 0, 0, 77, 0, 0, 0, - 80, 13, 0, 0, 46, 0, - 1, 0, 92, 13, 0, 0, - 81, 0, 0, 0, 104, 13, + 92, 13, 0, 0, 46, 0, + 1, 0, 104, 13, 0, 0, + 81, 0, 0, 0, 116, 13, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 68, 105, 102, 102, 117, @@ -651,7 +651,9 @@ const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 81, 0, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 81, 0, 0, 5, 243, 0, 15, 160, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 128, 63, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc index 6446b5eb..8fbbd439 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc @@ -32,7 +32,7 @@ dcl t1.xy // texCoord<0,1> dcl_2d s0 -#line 33 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SpriteEffect.fx" +#line 33 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SpriteEffect.fx" texld r0, t1, s0 mul r0, r0, t0 // ::SpritePixelShader<0,1,2,3> mov oC0, r0 // ::SpritePixelShader<0,1,2,3> @@ -53,31 +53,31 @@ ret const BYTE SpriteEffect_SpritePixelShader[] = { - 68, 88, 66, 67, 210, 231, - 76, 180, 17, 3, 192, 38, - 93, 177, 187, 117, 222, 165, - 188, 182, 1, 0, 0, 0, - 116, 3, 0, 0, 4, 0, + 68, 88, 66, 67, 83, 197, + 238, 212, 200, 62, 8, 111, + 190, 68, 117, 84, 180, 95, + 104, 220, 1, 0, 0, 0, + 128, 3, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 84, 2, 0, 0, 240, 2, - 0, 0, 64, 3, 0, 0, - 65, 111, 110, 57, 28, 2, - 0, 0, 28, 2, 0, 0, - 0, 2, 255, 255, 244, 1, + 96, 2, 0, 0, 252, 2, + 0, 0, 76, 3, 0, 0, + 65, 111, 110, 57, 40, 2, + 0, 0, 40, 2, 0, 0, + 0, 2, 255, 255, 0, 2, 0, 0, 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 2, 255, 255, 254, 255, - 102, 0, 68, 66, 85, 71, + 105, 0, 68, 66, 85, 71, 40, 0, 0, 0, 108, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 120, 0, 0, 0, 3, 0, 0, 0, 48, 1, 0, 0, - 168, 0, 0, 0, 67, 58, + 168, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -91,14 +91,14 @@ const BYTE SpriteEffect_SpritePixelShader[] = 114, 105, 116, 101, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, - 0, 0, 255, 255, 160, 1, + 0, 0, 255, 255, 172, 1, 0, 0, 0, 0, 255, 255, - 172, 1, 0, 0, 0, 0, - 255, 255, 184, 1, 0, 0, - 33, 0, 0, 0, 196, 1, + 184, 1, 0, 0, 0, 0, + 255, 255, 196, 1, 0, 0, + 33, 0, 0, 0, 208, 1, 0, 0, 33, 0, 0, 0, - 212, 1, 0, 0, 33, 0, - 0, 0, 228, 1, 0, 0, + 224, 1, 0, 0, 33, 0, + 0, 0, 240, 1, 0, 0, 83, 112, 114, 105, 116, 101, 80, 105, 120, 101, 108, 83, 104, 97, 100, 101, 114, 0, @@ -138,7 +138,9 @@ const BYTE SpriteEffect_SpritePixelShader[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc b/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc index fa065c57..db013a89 100644 --- a/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc +++ b/Kits/DirectXTK/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc @@ -42,7 +42,7 @@ dcl_texcoord1 v1 // texCoord<0,1> dcl_texcoord2 v2 // position<0,1,2,3> -#line 26 "C:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SpriteEffect.fx" +#line 26 "D:\ATG Sample Development\st_dev\Kits\DirectXTK\Src\Shaders\SpriteEffect.fx" mul r0, v2.y, c2 mad r0, v2.x, c1, r0 mad r0, v2.z, c3, r0 @@ -74,17 +74,17 @@ ret const BYTE SpriteEffect_SpriteVertexShader[] = { - 68, 88, 66, 67, 5, 73, - 202, 97, 204, 3, 14, 85, - 16, 11, 241, 197, 25, 93, - 20, 215, 1, 0, 0, 0, - 44, 5, 0, 0, 4, 0, + 68, 88, 66, 67, 105, 23, + 88, 21, 79, 231, 83, 120, + 151, 30, 36, 113, 187, 154, + 204, 234, 1, 0, 0, 0, + 56, 5, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, - 12, 3, 0, 0, 68, 4, - 0, 0, 184, 4, 0, 0, - 65, 111, 110, 57, 212, 2, - 0, 0, 212, 2, 0, 0, - 0, 2, 254, 255, 160, 2, + 24, 3, 0, 0, 80, 4, + 0, 0, 196, 4, 0, 0, + 65, 111, 110, 57, 224, 2, + 0, 0, 224, 2, 0, 0, + 0, 2, 254, 255, 172, 2, 0, 0, 52, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, @@ -93,14 +93,14 @@ const BYTE SpriteEffect_SpriteVertexShader[] = 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 254, 255, 254, 255, - 123, 0, 68, 66, 85, 71, + 126, 0, 68, 66, 85, 71, 40, 0, 0, 0, 192, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 116, 0, 0, 0, 11, 0, 0, 0, 120, 0, 0, 0, 3, 0, 0, 0, 132, 1, 0, 0, - 208, 0, 0, 0, 67, 58, + 208, 0, 0, 0, 68, 58, 92, 65, 84, 71, 32, 83, 97, 109, 112, 108, 101, 32, 68, 101, 118, 101, 108, 111, @@ -114,21 +114,21 @@ const BYTE SpriteEffect_SpriteVertexShader[] = 114, 105, 116, 101, 69, 102, 102, 101, 99, 116, 46, 102, 120, 0, 40, 0, 0, 0, - 0, 0, 255, 255, 244, 1, + 0, 0, 255, 255, 0, 2, 0, 0, 0, 0, 255, 255, - 0, 2, 0, 0, 0, 0, - 255, 255, 12, 2, 0, 0, - 26, 0, 0, 0, 24, 2, + 12, 2, 0, 0, 0, 0, + 255, 255, 24, 2, 0, 0, + 26, 0, 0, 0, 36, 2, 0, 0, 26, 0, 0, 0, - 40, 2, 0, 0, 26, 0, - 0, 0, 60, 2, 0, 0, - 26, 0, 0, 0, 80, 2, + 52, 2, 0, 0, 26, 0, + 0, 0, 72, 2, 0, 0, + 26, 0, 0, 0, 92, 2, 0, 0, 24, 0, 0, 0, - 100, 2, 0, 0, 24, 0, - 0, 0, 120, 2, 0, 0, - 22, 0, 0, 0, 132, 2, + 112, 2, 0, 0, 24, 0, + 0, 0, 132, 2, 0, 0, + 22, 0, 0, 0, 144, 2, 0, 0, 23, 0, 0, 0, - 144, 2, 0, 0, 83, 112, + 156, 2, 0, 0, 83, 112, 114, 105, 116, 101, 86, 101, 114, 116, 101, 120, 83, 104, 97, 100, 101, 114, 0, 99, @@ -175,7 +175,9 @@ const BYTE SpriteEffect_SpriteVertexShader[] = 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, - 49, 0, 31, 0, 0, 2, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128, 1, 0, diff --git a/Kits/DirectXTK/Src/SharedResourcePool.h b/Kits/DirectXTK/Src/SharedResourcePool.h index 1b060c57..459e35ca 100644 --- a/Kits/DirectXTK/Src/SharedResourcePool.h +++ b/Kits/DirectXTK/Src/SharedResourcePool.h @@ -25,7 +25,7 @@ namespace DirectX // This is used to avoid duplicate resource creation, so that for instance a caller can // create any number of SpriteBatch instances, but these can internally share shaders and // vertex buffer if more than one SpriteBatch uses the same underlying D3D device. - template + template class SharedResourcePool { public: @@ -37,7 +37,7 @@ namespace DirectX SharedResourcePool& operator= (SharedResourcePool const&) = delete; // Allocates or looks up the shared TData instance for the specified key. - std::shared_ptr DemandCreate(TKey key) + std::shared_ptr DemandCreate(TKey key, TConstructorArgs... args) { std::lock_guard lock(mResourceMap->mutex); @@ -55,7 +55,7 @@ namespace DirectX } // Allocate a new instance. - auto newValue = std::make_shared(key, mResourceMap); + auto newValue = std::make_shared(key, mResourceMap, args...); mResourceMap->insert(std::make_pair(key, newValue)); @@ -77,10 +77,10 @@ namespace DirectX // to remove instances from our pool before they are freed. struct WrappedData : public TData { - WrappedData(TKey key, std::shared_ptr const& resourceMap) + WrappedData(TKey key, std::shared_ptr const& resourceMap, TConstructorArgs... args) : mKey(key), mResourceMap(resourceMap), - TData(key) + TData(key, args...) { } ~WrappedData() diff --git a/Kits/DirectXTK/Src/SimpleMath.cpp b/Kits/DirectXTK/Src/SimpleMath.cpp index 52341591..6fee5930 100644 --- a/Kits/DirectXTK/Src/SimpleMath.cpp +++ b/Kits/DirectXTK/Src/SimpleMath.cpp @@ -97,6 +97,7 @@ namespace DirectX * ****************************************************************************/ +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) static_assert(sizeof(DirectX::SimpleMath::Viewport) == sizeof(D3D11_VIEWPORT), "Size mismatch"); static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, x) == FIELD_OFFSET(D3D11_VIEWPORT, TopLeftX), "Layout mismatch"); static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, y) == FIELD_OFFSET(D3D11_VIEWPORT, TopLeftY), "Layout mismatch"); @@ -104,6 +105,17 @@ static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, width) == FIELD_OFFSET static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, height) == FIELD_OFFSET(D3D11_VIEWPORT, Height), "Layout mismatch"); static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, minDepth) == FIELD_OFFSET(D3D11_VIEWPORT, MinDepth), "Layout mismatch"); static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, maxDepth) == FIELD_OFFSET(D3D11_VIEWPORT, MaxDepth), "Layout mismatch"); +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +static_assert(sizeof(DirectX::SimpleMath::Viewport) == sizeof(D3D12_VIEWPORT), "Size mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, x) == FIELD_OFFSET(D3D12_VIEWPORT, TopLeftX), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, y) == FIELD_OFFSET(D3D12_VIEWPORT, TopLeftY), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, width) == FIELD_OFFSET(D3D12_VIEWPORT, Width), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, height) == FIELD_OFFSET(D3D12_VIEWPORT, Height), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, minDepth) == FIELD_OFFSET(D3D12_VIEWPORT, MinDepth), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, maxDepth) == FIELD_OFFSET(D3D12_VIEWPORT, MaxDepth), "Layout mismatch"); +#endif RECT DirectX::SimpleMath::Viewport::ComputeDisplayArea(DXGI_SCALING scaling, UINT backBufferWidth, UINT backBufferHeight, int outputWidth, int outputHeight) { diff --git a/Kits/DirectXTK/Src/SpriteFont.cpp b/Kits/DirectXTK/Src/SpriteFont.cpp index c938cd48..7aee7259 100644 --- a/Kits/DirectXTK/Src/SpriteFont.cpp +++ b/Kits/DirectXTK/Src/SpriteFont.cpp @@ -203,14 +203,16 @@ void SpriteFont::Impl::ForEachGlyph(_In_z_ wchar_t const* text, TAction action) if (x < 0) x = 0; + float advance = glyph->Subrect.right - glyph->Subrect.left + glyph->XAdvance; + if ( !iswspace(character) || ( ( glyph->Subrect.right - glyph->Subrect.left ) > 1 ) || ( ( glyph->Subrect.bottom - glyph->Subrect.top ) > 1 ) ) { - action(glyph, x, y); + action(glyph, x, y, advance); } - x += glyph->Subrect.right - glyph->Subrect.left + glyph->XAdvance; + x += advance; break; } } @@ -315,8 +317,10 @@ void XM_CALLCONV SpriteFont::DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wc } // Draw each character in turn. - pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y) + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) { + UNREFERENCED_PARAMETER(advance); + XMVECTOR offset = XMVectorMultiplyAdd(XMVectorSet(x, y + glyph->YOffset, 0, 0), axisDirectionTable[effects & 3], baseOffset); if (effects) @@ -339,9 +343,11 @@ XMVECTOR XM_CALLCONV SpriteFont::MeasureString(_In_z_ wchar_t const* text) const { XMVECTOR result = XMVectorZero(); - pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y) + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) { - float w = (float)(glyph->Subrect.right - glyph->Subrect.left) + glyph->XAdvance; + UNREFERENCED_PARAMETER(advance); + + float w = (float)(glyph->Subrect.right - glyph->Subrect.left); float h = (float)(glyph->Subrect.bottom - glyph->Subrect.top) + glyph->YOffset; h = std::max(h, pImpl->lineSpacing); @@ -353,6 +359,53 @@ XMVECTOR XM_CALLCONV SpriteFont::MeasureString(_In_z_ wchar_t const* text) const } +RECT SpriteFont::MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position) const +{ + RECT result = { LONG_MAX, LONG_MAX, 0, 0 }; + + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) + { + float w = (float)(glyph->Subrect.right - glyph->Subrect.left); + float h = (float)(glyph->Subrect.bottom - glyph->Subrect.top); + + float minX = position.x + x; + float minY = position.y + y + glyph->YOffset; + + float maxX = std::max(minX + advance, minX + w); + float maxY = minY + h; + + if (minX < result.left) + result.left = long(minX); + + if (minY < result.top) + result.top = long(minY); + + if (result.right < maxX) + result.right = long(maxX); + + if (result.bottom < maxY) + result.bottom = long(maxY); + }); + + if (result.left == LONG_MAX) + { + result.left = 0; + result.top = 0; + } + + return result; +} + + +RECT XM_CALLCONV SpriteFont::MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position) const +{ + XMFLOAT2 pos; + XMStoreFloat2(&pos, position); + + return MeasureDrawBounds(text, pos); +} + + // Spacing properties float SpriteFont::GetLineSpacing() const { diff --git a/Kits/DirectXTK/Src/WICTextureLoader.cpp b/Kits/DirectXTK/Src/WICTextureLoader.cpp index 5a954522..be4d7783 100644 --- a/Kits/DirectXTK/Src/WICTextureLoader.cpp +++ b/Kits/DirectXTK/Src/WICTextureLoader.cpp @@ -30,12 +30,11 @@ #include "pch.h" -#include - #include "WICTextureLoader.h" #include "DirectXHelpers.h" #include "PlatformHelpers.h" +#include "LoaderHelpers.h" using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -265,37 +264,6 @@ namespace return bpp; } - //-------------------------------------------------------------------------------------- - DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) - { - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - - case DXGI_FORMAT_BC1_UNORM: - return DXGI_FORMAT_BC1_UNORM_SRGB; - - case DXGI_FORMAT_BC2_UNORM: - return DXGI_FORMAT_BC2_UNORM_SRGB; - - case DXGI_FORMAT_BC3_UNORM: - return DXGI_FORMAT_BC3_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; - - case DXGI_FORMAT_B8G8R8X8_UNORM: - return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; - - case DXGI_FORMAT_BC7_UNORM: - return DXGI_FORMAT_BC7_UNORM_SRGB; - - default: - return format; - } - } - //--------------------------------------------------------------------------------- HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice, _In_opt_ ID3D11DeviceContext* d3dContext, diff --git a/Kits/DirectXTK/Src/dds.h b/Kits/DirectXTK/Src/dds.h index 282a802e..3bd63cd9 100644 --- a/Kits/DirectXTK/Src/dds.h +++ b/Kits/DirectXTK/Src/dds.h @@ -21,14 +21,6 @@ #pragma once -#if defined(_XBOX_ONE) && defined(_TITLE) -#include -#else -#include -#endif - -#include - namespace DirectX { @@ -233,4 +225,4 @@ struct DDS_HEADER_DXT10 static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); -}; // namespace +} // namespace diff --git a/Kits/DirectXTK/Src/pch.h b/Kits/DirectXTK/Src/pch.h index 3f264612..08b2575b 100644 --- a/Kits/DirectXTK/Src/pch.h +++ b/Kits/DirectXTK/Src/pch.h @@ -59,8 +59,11 @@ #include #include #include +#include #include #include #include + +#include diff --git a/Kits/DirectXTK/Src/vbo.h b/Kits/DirectXTK/Src/vbo.h new file mode 100644 index 00000000..5087ed1c --- /dev/null +++ b/Kits/DirectXTK/Src/vbo.h @@ -0,0 +1,38 @@ +//-------------------------------------------------------------------------------------- +// File: vbo.h +// +// The VBO file format was introduced in the Windows 8.0 ResourceLoading sample. It's +// a simple binary file containing a 16-bit index buffer and a fixed-format vertex buffer. +// +// The meshconvert sample tool for DirectXMesh can produce this file type +// http://go.microsoft.com/fwlink/?LinkID=324981 +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + + +namespace VBO +{ +#pragma pack(push,1) + + struct header_t + { + uint32_t numVertices; + uint32_t numIndices; + }; + +#pragma pack(pop) + +}; // namespace + +static_assert(sizeof(VBO::header_t) == 8, "VBO header size mismatch"); + diff --git a/Kits/DirectXTK12/Audio/AudioEngine.cpp b/Kits/DirectXTK12/Audio/AudioEngine.cpp new file mode 100644 index 00000000..80980b22 --- /dev/null +++ b/Kits/DirectXTK12/Audio/AudioEngine.cpp @@ -0,0 +1,1724 @@ +//-------------------------------------------------------------------------------------- +// File: AudioEngine.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Audio.h" +#include "SoundCommon.h" + +#include +#include + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +//#define VERBOSE_TRACE + + +namespace +{ + struct EngineCallback : public IXAudio2EngineCallback + { + EngineCallback() + { + mCriticalError.reset( CreateEventEx( nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !mCriticalError ) + { + throw std::exception( "CreateEvent" ); + } + }; + + virtual ~EngineCallback() + { + } + + STDMETHOD_(void, OnProcessingPassStart) () override {} + STDMETHOD_(void, OnProcessingPassEnd)() override {} + + STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT error) + { +#ifndef _DEBUG + UNREFERENCED_PARAMETER(error); +#endif + DebugTrace( "ERROR: AudioEngine encountered critical error (%08X)\n", error ); + SetEvent( mCriticalError.get() ); + } + + ScopedHandle mCriticalError; + }; + + struct VoiceCallback : public IXAudio2VoiceCallback + { + VoiceCallback() + { + mBufferEnd.reset( CreateEventEx( nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !mBufferEnd ) + { + throw std::exception( "CreateEvent" ); + } + } + + virtual ~VoiceCallback() + { + } + + STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) override {} + STDMETHOD_(void, OnVoiceProcessingPassEnd)() override {} + STDMETHOD_(void, OnStreamEnd)() override {} + STDMETHOD_(void, OnBufferStart)( void* ) override {} + + STDMETHOD_(void, OnBufferEnd)( void* context ) override + { + if ( context ) + { + auto inotify = reinterpret_cast( context ); + inotify->OnBufferEnd(); + SetEvent( mBufferEnd.get() ); + } + } + + STDMETHOD_(void, OnLoopEnd)( void* ) override {} + STDMETHOD_(void, OnVoiceError)( void*, HRESULT ) override {} + + ScopedHandle mBufferEnd; + }; + + static const XAUDIO2FX_REVERB_I3DL2_PARAMETERS gReverbPresets[] = + { + XAUDIO2FX_I3DL2_PRESET_DEFAULT, // Reverb_Off + XAUDIO2FX_I3DL2_PRESET_DEFAULT, // Reverb_Default + XAUDIO2FX_I3DL2_PRESET_GENERIC, // Reverb_Generic + XAUDIO2FX_I3DL2_PRESET_FOREST, // Reverb_Forest + XAUDIO2FX_I3DL2_PRESET_PADDEDCELL, // Reverb_PaddedCell + XAUDIO2FX_I3DL2_PRESET_ROOM, // Reverb_Room + XAUDIO2FX_I3DL2_PRESET_BATHROOM, // Reverb_Bathroom + XAUDIO2FX_I3DL2_PRESET_LIVINGROOM, // Reverb_LivingRoom + XAUDIO2FX_I3DL2_PRESET_STONEROOM, // Reverb_StoneRoom + XAUDIO2FX_I3DL2_PRESET_AUDITORIUM, // Reverb_Auditorium + XAUDIO2FX_I3DL2_PRESET_CONCERTHALL, // Reverb_ConcertHall + XAUDIO2FX_I3DL2_PRESET_CAVE, // Reverb_Cave + XAUDIO2FX_I3DL2_PRESET_ARENA, // Reverb_Arena + XAUDIO2FX_I3DL2_PRESET_HANGAR, // Reverb_Hangar + XAUDIO2FX_I3DL2_PRESET_CARPETEDHALLWAY, // Reverb_CarpetedHallway + XAUDIO2FX_I3DL2_PRESET_HALLWAY, // Reverb_Hallway + XAUDIO2FX_I3DL2_PRESET_STONECORRIDOR, // Reverb_StoneCorridor + XAUDIO2FX_I3DL2_PRESET_ALLEY, // Reverb_Alley + XAUDIO2FX_I3DL2_PRESET_CITY, // Reverb_City + XAUDIO2FX_I3DL2_PRESET_MOUNTAINS, // Reverb_Mountains + XAUDIO2FX_I3DL2_PRESET_QUARRY, // Reverb_Quarry + XAUDIO2FX_I3DL2_PRESET_PLAIN, // Reverb_Plain + XAUDIO2FX_I3DL2_PRESET_PARKINGLOT, // Reverb_ParkingLot + XAUDIO2FX_I3DL2_PRESET_SEWERPIPE, // Reverb_SewerPipe + XAUDIO2FX_I3DL2_PRESET_UNDERWATER, // Reverb_Underwater + XAUDIO2FX_I3DL2_PRESET_SMALLROOM, // Reverb_SmallRoom + XAUDIO2FX_I3DL2_PRESET_MEDIUMROOM, // Reverb_MediumRoom + XAUDIO2FX_I3DL2_PRESET_LARGEROOM, // Reverb_LargeRoom + XAUDIO2FX_I3DL2_PRESET_MEDIUMHALL, // Reverb_MediumHall + XAUDIO2FX_I3DL2_PRESET_LARGEHALL, // Reverb_LargeHall + XAUDIO2FX_I3DL2_PRESET_PLATE, // Reverb_Plate + }; + + inline unsigned int makeVoiceKey( _In_ const WAVEFORMATEX* wfx ) + { + assert( IsValid(wfx) ); + + if ( wfx->nChannels > 0x7F ) + return 0; + + union KeyGen + { + struct + { + unsigned int tag : 9; + unsigned int channels : 7; + unsigned int bitsPerSample : 8; + } pcm; + + struct + { + unsigned int tag : 9; + unsigned int channels : 7; + unsigned int samplesPerBlock : 16; + } adpcm; + +#if defined(_XBOX_ONE) && defined(_TITLE) + struct + { + unsigned int tag : 9; + unsigned int channels : 7; + unsigned int encoderVersion : 8; + } xma; +#endif + + unsigned int key; + } result; + + static_assert( sizeof(KeyGen) == sizeof(unsigned int), "KeyGen is invalid" ); + + result.key = 0; + + if ( wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) + { + // We reuse EXTENSIBLE only if it is equivalent to the standard form + auto wfex = reinterpret_cast( wfx ); + if ( wfex->Samples.wValidBitsPerSample != 0 && wfex->Samples.wValidBitsPerSample != wfx->wBitsPerSample ) + return 0; + + if ( wfex->dwChannelMask != 0 && wfex->dwChannelMask != GetDefaultChannelMask( wfx->nChannels ) ) + return 0; + } + + uint32_t tag = GetFormatTag( wfx ); + switch( tag ) + { + case WAVE_FORMAT_PCM: + static_assert( WAVE_FORMAT_PCM < 0x1ff, "KeyGen tag is too small" ); + result.pcm.tag = WAVE_FORMAT_PCM; + result.pcm.channels = wfx->nChannels; + result.pcm.bitsPerSample = wfx->wBitsPerSample; + break; + + case WAVE_FORMAT_IEEE_FLOAT: + static_assert( WAVE_FORMAT_IEEE_FLOAT < 0x1ff, "KeyGen tag is too small" ); + + if ( wfx->wBitsPerSample != 32 ) + return 0; + + result.pcm.tag = WAVE_FORMAT_IEEE_FLOAT; + result.pcm.channels = wfx->nChannels; + result.pcm.bitsPerSample = 32; + break; + + case WAVE_FORMAT_ADPCM: + static_assert( WAVE_FORMAT_ADPCM < 0x1ff, "KeyGen tag is too small" ); + result.adpcm.tag = WAVE_FORMAT_ADPCM; + result.adpcm.channels = wfx->nChannels; + + { + auto wfadpcm = reinterpret_cast( wfx ); + result.adpcm.samplesPerBlock = wfadpcm->wSamplesPerBlock; + } + break; + +#if defined(_XBOX_ONE) && defined(_TITLE) + case WAVE_FORMAT_XMA2: + static_assert( WAVE_FORMAT_XMA2 < 0x1ff, "KeyGen tag is too small" ); + result.xma.tag = WAVE_FORMAT_XMA2; + result.xma.channels = wfx->nChannels; + + { + auto xmaFmt = reinterpret_cast( wfx ); + + if ( ( xmaFmt->LoopBegin > 0 ) + || ( xmaFmt->PlayBegin > 0 ) ) + return 0; + + result.xma.encoderVersion = xmaFmt->EncoderVersion; + } + break; +#endif + + default: + return 0; + } + + return result.key; + } +} + +static_assert( _countof(gReverbPresets) == Reverb_MAX, "AUDIO_ENGINE_REVERB enum mismatch" ); + + +//====================================================================================== +// AudioEngine +//====================================================================================== + +#define SAFE_DESTROY_VOICE(voice) if ( voice ) { voice->DestroyVoice(); voice = nullptr; } + +// Internal object implementation class. +class AudioEngine::Impl +{ +public: + Impl() : + mMasterVoice( nullptr ), + mReverbVoice( nullptr ), + masterChannelMask( 0 ), + masterChannels( 0 ), + masterRate( 0 ), + defaultRate( 44100 ), + maxVoiceOneshots( SIZE_MAX ), + maxVoiceInstances( SIZE_MAX ), + mMasterVolume( 1.f ), + mCriticalError( false ), + mReverbEnabled( false ), + mEngineFlags( AudioEngine_Default ), + mCategory( AudioCategory_GameEffects ), + mVoiceInstances( 0 ) +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + ,mDLL(nullptr) +#endif + { + memset( &mX3DAudio, 0, X3DAUDIO_HANDLE_BYTESIZE ); + }; + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + ~Impl() + { + if (mDLL) + { + FreeLibrary(mDLL); + mDLL = nullptr; + } + } +#endif + + HRESULT Initialize( AUDIO_ENGINE_FLAGS flags, _In_opt_ const WAVEFORMATEX* wfx, _In_opt_z_ const wchar_t* deviceId, AUDIO_STREAM_CATEGORY category ); + + HRESULT Reset( _In_opt_ const WAVEFORMATEX* wfx, _In_opt_z_ const wchar_t* deviceId ); + + void SetSilentMode(); + + void Shutdown(); + + bool Update(); + + void SetReverb( _In_opt_ const XAUDIO2FX_REVERB_PARAMETERS* native ); + + void SetMasteringLimit( int release, int loudness ); + + AudioStatistics GetStatistics() const; + + void TrimVoicePool(); + + void AllocateVoice( _In_ const WAVEFORMATEX* wfx, SOUND_EFFECT_INSTANCE_FLAGS flags, bool oneshot, _Outptr_result_maybenull_ IXAudio2SourceVoice** voice ); + void DestroyVoice( _In_ IXAudio2SourceVoice* voice ); + + void RegisterNotify( _In_ IVoiceNotify* notify, bool usesUpdate ); + void UnregisterNotify( _In_ IVoiceNotify* notify, bool oneshots, bool usesUpdate ); + + ComPtr xaudio2; + IXAudio2MasteringVoice* mMasterVoice; + IXAudio2SubmixVoice* mReverbVoice; + + uint32_t masterChannelMask; + uint32_t masterChannels; + uint32_t masterRate; + + int defaultRate; + size_t maxVoiceOneshots; + size_t maxVoiceInstances; + float mMasterVolume; + + X3DAUDIO_HANDLE mX3DAudio; + + bool mCriticalError; + bool mReverbEnabled; + + AUDIO_ENGINE_FLAGS mEngineFlags; + +private: + typedef std::set notifylist_t; + typedef std::list> oneshotlist_t; + typedef std::unordered_multimap voicepool_t; + + AUDIO_STREAM_CATEGORY mCategory; + ComPtr mReverbEffect; + ComPtr mVolumeLimiter; + oneshotlist_t mOneShots; + voicepool_t mVoicePool; + notifylist_t mNotifyObjects; + notifylist_t mNotifyUpdates; + size_t mVoiceInstances; + VoiceCallback mVoiceCallback; + EngineCallback mEngineCallback; + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + HMODULE mDLL; +#endif +}; + + +_Use_decl_annotations_ +HRESULT AudioEngine::Impl::Initialize( AUDIO_ENGINE_FLAGS flags, const WAVEFORMATEX* wfx, const wchar_t* deviceId, AUDIO_STREAM_CATEGORY category ) +{ + mEngineFlags = flags; + mCategory = category; + + return Reset( wfx, deviceId ); +} + + +_Use_decl_annotations_ +HRESULT AudioEngine::Impl::Reset( const WAVEFORMATEX* wfx, const wchar_t* deviceId ) +{ + if ( wfx ) + { + if ( wfx->wFormatTag != WAVE_FORMAT_PCM ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + if ( !wfx->nChannels || wfx->nChannels > XAUDIO2_MAX_AUDIO_CHANNELS ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + if ( wfx->nSamplesPerSec < XAUDIO2_MIN_SAMPLE_RATE || wfx->nSamplesPerSec > XAUDIO2_MAX_SAMPLE_RATE ) + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + // We don't use other data members of WAVEFORMATEX here to describe the device format, so no need to fully validate + } + + assert( !xaudio2 ); + assert( !mMasterVoice ); + assert( !mReverbVoice ); + + masterChannelMask = masterChannels = masterRate = 0; + + memset( &mX3DAudio, 0, X3DAUDIO_HANDLE_BYTESIZE ); + + mCriticalError = false; + mReverbEnabled = false; + + // + // Create XAudio2 engine + // + UINT32 eflags = 0; +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + if ( mEngineFlags & AudioEngine_Debug ) + { + if ( !mDLL ) + { + mDLL = LoadLibraryEx( L"XAudioD2_7.DLL", nullptr, 0x00000800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ ); + if ( !mDLL ) + { + DebugTrace( "ERROR: XAudio 2.7 debug version not installed on system (install the DirectX SDK Developer Runtime)\n" ); + return HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); + } + } + + eflags |= XAUDIO2_DEBUG_ENGINE; + } + else if ( !mDLL ) + { + mDLL = LoadLibraryEx( L"XAudio2_7.DLL", nullptr, 0x00000800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ ); + if ( !mDLL ) + { + DebugTrace( "ERROR: XAudio 2.7 not installed on system (install the DirectX End-user Runtimes (June 2010))\n" ); + return HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); + } + } +#endif + + HRESULT hr = XAudio2Create( xaudio2.ReleaseAndGetAddressOf(), eflags ); + if( FAILED( hr ) ) + { +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + DebugTrace( "ERROR: XAudio 2.7 not found (have you called CoInitialize?)\n" ); +#endif + return hr; + } + + if ( mEngineFlags & AudioEngine_Debug ) + { + XAUDIO2_DEBUG_CONFIGURATION debug = {}; + debug.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS; + debug.BreakMask = XAUDIO2_LOG_ERRORS; + xaudio2->SetDebugConfiguration( &debug, nullptr ); +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10) || defined(_XBOX_ONE) + DebugTrace("INFO: XAudio 2.9 debugging enabled\n"); +#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + // To see the trace output, you need to view ETW logs for this application: + // Go to Control Panel, Administrative Tools, Event Viewer. + // View->Show Analytic and Debug Logs. + // Applications and Services Logs / Microsoft / Windows / XAudio2. + // Right click on Microsoft Windows XAudio2 debug logging, Properties, then Enable Logging, and hit OK + DebugTrace( "INFO: XAudio 2.8 debugging enabled\n" ); +#else + // To see the trace output, see the debug output channel window + DebugTrace( "INFO: XAudio 2.7 debugging enabled\n" ); +#endif + } + + if ( mEngineFlags & AudioEngine_DisableVoiceReuse ) + { + DebugTrace( "INFO: Voice reuse is disabled\n" ); + } + + hr = xaudio2->RegisterForCallbacks( &mEngineCallback ); + if ( FAILED(hr) ) + { + xaudio2.Reset(); + return hr; + } + + // + // Create mastering voice for device + // + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + + hr = xaudio2->CreateMasteringVoice( &mMasterVoice, + (wfx) ? wfx->nChannels : XAUDIO2_DEFAULT_CHANNELS, + (wfx) ? wfx->nSamplesPerSec : XAUDIO2_DEFAULT_SAMPLERATE, + 0, deviceId, nullptr, mCategory ); + if ( FAILED(hr) ) + { + xaudio2.Reset(); + return hr; + } + + DWORD dwChannelMask; + hr = mMasterVoice->GetChannelMask( &dwChannelMask ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + xaudio2.Reset(); + return hr; + } + + XAUDIO2_VOICE_DETAILS details; + mMasterVoice->GetVoiceDetails( &details ); + + masterChannelMask = dwChannelMask; + masterChannels = details.InputChannels; + masterRate = details.InputSampleRate; + +#else + + UINT32 count = 0; + hr = xaudio2->GetDeviceCount( &count ); + if ( FAILED(hr) ) + { + xaudio2.Reset(); + return hr; + } + + if ( !count ) + { + xaudio2.Reset(); + return HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); + } + + UINT32 devIndex = 0; + if ( deviceId ) + { + // Translate device ID back into device index + devIndex = UINT32(-1); + for( UINT32 j = 0; j < count; ++j ) + { + XAUDIO2_DEVICE_DETAILS details; + hr = xaudio2->GetDeviceDetails( j, &details ); + if ( SUCCEEDED(hr) ) + { + if ( wcsncmp( deviceId, details.DeviceID, 256 ) == 0 ) + { + devIndex = j; + masterChannelMask = details.OutputFormat.dwChannelMask; + break; + } + } + } + + if ( devIndex == UINT32(-1) ) + { + xaudio2.Reset(); + return HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); + } + } + else + { + // No search needed + XAUDIO2_DEVICE_DETAILS details; + hr = xaudio2->GetDeviceDetails( 0, &details ); + if ( FAILED(hr) ) + { + xaudio2.Reset(); + return hr; + } + + masterChannelMask = details.OutputFormat.dwChannelMask; + } + + hr = xaudio2->CreateMasteringVoice( &mMasterVoice, + (wfx) ? wfx->nChannels : XAUDIO2_DEFAULT_CHANNELS, + (wfx) ? wfx->nSamplesPerSec : XAUDIO2_DEFAULT_SAMPLERATE, + 0, devIndex, nullptr ); + if ( FAILED(hr) ) + { + xaudio2.Reset(); + return hr; + } + + XAUDIO2_VOICE_DETAILS details; + mMasterVoice->GetVoiceDetails( &details ); + + masterChannels = details.InputChannels; + masterRate = details.InputSampleRate; + +#endif + + DebugTrace( "INFO: mastering voice has %u channels, %u sample rate, %08X channel mask\n", masterChannels, masterRate, masterChannelMask ); + + if ( mMasterVolume != 1.f ) + { + hr = mMasterVoice->SetVolume( mMasterVolume ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + xaudio2.Reset(); + return hr; + } + } + + // + // Setup mastering volume limiter (optional) + // + if ( mEngineFlags & AudioEngine_UseMasteringLimiter ) + { + FXMASTERINGLIMITER_PARAMETERS params = {}; + params.Release = FXMASTERINGLIMITER_DEFAULT_RELEASE; + params.Loudness = FXMASTERINGLIMITER_DEFAULT_LOUDNESS; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + hr = CreateFX( __uuidof(FXMasteringLimiter), mVolumeLimiter.ReleaseAndGetAddressOf(), ¶ms, sizeof(params) ); +#else + hr = CreateFX( __uuidof(FXMasteringLimiter), mVolumeLimiter.ReleaseAndGetAddressOf() ); +#endif + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + xaudio2.Reset(); + return hr; + } + + XAUDIO2_EFFECT_DESCRIPTOR desc = {}; + desc.InitialState = TRUE; + desc.OutputChannels = masterChannels; + desc.pEffect = mVolumeLimiter.Get(); + + XAUDIO2_EFFECT_CHAIN chain = { 1, &desc }; + hr = mMasterVoice->SetEffectChain( &chain ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + hr = mMasterVoice->SetEffectParameters( 0, ¶ms, sizeof(params) ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } +#endif + + DebugTrace( "INFO: Mastering volume limiter enabled\n" ); + } + + // + // Setup environmental reverb for 3D audio (optional) + // + if ( mEngineFlags & AudioEngine_EnvironmentalReverb ) + { + UINT32 rflags = 0; +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + if ( mEngineFlags & AudioEngine_Debug ) + { + rflags |= XAUDIO2FX_DEBUG; + } +#endif + hr = XAudio2CreateReverb( mReverbEffect.ReleaseAndGetAddressOf(), rflags ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } + + XAUDIO2_EFFECT_DESCRIPTOR effects[] = { { mReverbEffect.Get(), TRUE, 1 } }; + XAUDIO2_EFFECT_CHAIN effectChain = { 1, effects }; + + mReverbEnabled = true; + + hr = xaudio2->CreateSubmixVoice( &mReverbVoice, 1, masterRate, + (mEngineFlags & AudioEngine_ReverbUseFilters ) ? XAUDIO2_VOICE_USEFILTER : 0, 0, + nullptr, &effectChain ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mMasterVoice ); + mReverbEffect.Reset(); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } + + XAUDIO2FX_REVERB_PARAMETERS native; + ReverbConvertI3DL2ToNative( &gReverbPresets[ Reverb_Default ], &native ); + hr = mReverbVoice->SetEffectParameters( 0, &native, sizeof( XAUDIO2FX_REVERB_PARAMETERS ) ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mReverbVoice ); + SAFE_DESTROY_VOICE( mMasterVoice ); + mReverbEffect.Reset(); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } + + DebugTrace( "INFO: I3DL2 reverb effect enabled for 3D positional audio\n" ); + } + + // + // Setup 3D audio + // + const float SPEEDOFSOUND = X3DAUDIO_SPEED_OF_SOUND; + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + hr = X3DAudioInitialize( masterChannelMask, SPEEDOFSOUND, mX3DAudio ); + if ( FAILED(hr) ) + { + SAFE_DESTROY_VOICE( mReverbVoice ); + SAFE_DESTROY_VOICE( mMasterVoice ); + mReverbEffect.Reset(); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + return hr; + } +#else + X3DAudioInitialize( masterChannelMask, SPEEDOFSOUND, mX3DAudio ); +#endif + + // + // Inform any notify objects we are ready to go again + // + for( auto it = mNotifyObjects.begin(); it != mNotifyObjects.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnReset(); + } + + return S_OK; +} + + +void AudioEngine::Impl::SetSilentMode() +{ + for( auto it = mNotifyObjects.begin(); it != mNotifyObjects.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnCriticalError(); + } + + for( auto it = mOneShots.begin(); it != mOneShots.end(); ++it ) + { + assert( it->second != 0 ); + it->second->DestroyVoice(); + } + mOneShots.clear(); + + for( auto it = mVoicePool.begin(); it != mVoicePool.end(); ++it ) + { + assert( it->second != 0 ); + it->second->DestroyVoice(); + } + mVoicePool.clear(); + + mVoiceInstances = 0; + + SAFE_DESTROY_VOICE( mReverbVoice ); + SAFE_DESTROY_VOICE( mMasterVoice ); + + mReverbEffect.Reset(); + mVolumeLimiter.Reset(); + xaudio2.Reset(); +} + + +void AudioEngine::Impl::Shutdown() +{ + for( auto it = mNotifyObjects.begin(); it != mNotifyObjects.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnDestroyEngine(); + } + + if ( xaudio2 ) + { + xaudio2->UnregisterForCallbacks( &mEngineCallback ); + + xaudio2->StopEngine(); + + for( auto it = mOneShots.begin(); it != mOneShots.end(); ++it ) + { + assert( it->second != 0 ); + it->second->DestroyVoice(); + } + mOneShots.clear(); + + for( auto it = mVoicePool.begin(); it != mVoicePool.end(); ++it ) + { + assert( it->second != 0 ); + it->second->DestroyVoice(); + } + mVoicePool.clear(); + + mVoiceInstances = 0; + + SAFE_DESTROY_VOICE( mReverbVoice ); + SAFE_DESTROY_VOICE( mMasterVoice ); + + mReverbEffect.Reset(); + mVolumeLimiter.Reset(); + xaudio2.Reset(); + + masterChannelMask = masterChannels = masterRate = 0; + + mCriticalError = false; + mReverbEnabled = false; + + memset( &mX3DAudio, 0, X3DAUDIO_HANDLE_BYTESIZE ); + } +} + + +bool AudioEngine::Impl::Update() +{ + if ( !xaudio2 ) + return false; + + HANDLE events[2] = { mEngineCallback.mCriticalError.get(), mVoiceCallback.mBufferEnd.get() }; + DWORD result = WaitForMultipleObjectsEx( 2, events, FALSE, 0, FALSE ); + switch( result ) + { + case WAIT_TIMEOUT: + break; + + case WAIT_OBJECT_0: // OnCritialError + mCriticalError = true; + + SetSilentMode(); + return false; + + case WAIT_OBJECT_0 + 1: // OnBufferEnd + // Scan for completed one-shot voices + for( auto it = mOneShots.begin(); it != mOneShots.end(); ) + { + assert( it->second != 0 ); + + XAUDIO2_VOICE_STATE xstate; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + it->second->GetState( &xstate, XAUDIO2_VOICE_NOSAMPLESPLAYED ); +#else + it->second->GetState( &xstate ); +#endif + + if ( !xstate.BuffersQueued ) + { + it->second->Stop( 0 ); + if ( it->first ) + { + // Put voice back into voice pool for reuse since it has a non-zero voiceKey +#ifdef VERBOSE_TRACE + DebugTrace( "INFO: One-shot voice being saved for reuse (%08X)\n", it->first ); +#endif + voicepool_t::value_type v( it->first, it->second ); + mVoicePool.emplace( v ); + } + else + { + // Voice is to be destroyed rather than reused +#ifdef VERBOSE_TRACE + DebugTrace( "INFO: Destroying one-shot voice\n" ); +#endif + it->second->DestroyVoice(); + } + it = mOneShots.erase( it ); + } + else + ++it; + } + break; + + case WAIT_FAILED: + throw std::exception( "WaitForMultipleObjects" ); + } + + // + // Inform any notify objects of updates + // + for( auto it = mNotifyUpdates.begin(); it != mNotifyUpdates.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnUpdate(); + } + + return true; +} + + +_Use_decl_annotations_ +void AudioEngine::Impl::SetReverb( const XAUDIO2FX_REVERB_PARAMETERS* native ) +{ + if ( !mReverbVoice ) + return; + + if ( native ) + { + if ( !mReverbEnabled ) + { + mReverbEnabled = true; + mReverbVoice->EnableEffect( 0 ); + } + + mReverbVoice->SetEffectParameters( 0, native, sizeof( XAUDIO2FX_REVERB_PARAMETERS ) ); + } + else if ( mReverbEnabled ) + { + mReverbEnabled = false; + mReverbVoice->DisableEffect( 0 ); + } +} + + +void AudioEngine::Impl::SetMasteringLimit( int release, int loudness ) +{ + if ( !mVolumeLimiter || !mMasterVoice ) + return; + + if ( ( release < FXMASTERINGLIMITER_MIN_RELEASE ) || ( release > FXMASTERINGLIMITER_MAX_RELEASE ) ) + throw std::out_of_range( "AudioEngine::SetMasteringLimit" ); + + if ( ( loudness < FXMASTERINGLIMITER_MIN_LOUDNESS ) || ( loudness > FXMASTERINGLIMITER_MAX_LOUDNESS ) ) + throw std::out_of_range( "AudioEngine::SetMasteringLimit" ); + + FXMASTERINGLIMITER_PARAMETERS params = {}; + params.Release = static_cast( release ); + params.Loudness = static_cast( loudness ); + + HRESULT hr = mMasterVoice->SetEffectParameters( 0, ¶ms, sizeof(params) ); + ThrowIfFailed( hr ); +} + + +AudioStatistics AudioEngine::Impl::GetStatistics() const +{ + AudioStatistics stats = {}; + + stats.allocatedVoices = stats.allocatedVoicesOneShot = mOneShots.size() + mVoicePool.size(); + stats.allocatedVoicesIdle = mVoicePool.size(); + + for( auto it = mNotifyObjects.begin(); it != mNotifyObjects.end(); ++it ) + { + assert( *it != 0 ); + (*it)->GatherStatistics( stats ); + } + + assert( stats.allocatedVoices == ( mOneShots.size() + mVoicePool.size() + mVoiceInstances ) ); + + return stats; +} + + +void AudioEngine::Impl::TrimVoicePool() +{ + for( auto it = mNotifyObjects.begin(); it != mNotifyObjects.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnTrim(); + } + + for( auto it = mVoicePool.begin(); it != mVoicePool.end(); ++it ) + { + assert( it->second != 0 ); + it->second->DestroyVoice(); + } + mVoicePool.clear(); +} + + +_Use_decl_annotations_ +void AudioEngine::Impl::AllocateVoice( const WAVEFORMATEX* wfx, SOUND_EFFECT_INSTANCE_FLAGS flags, bool oneshot, IXAudio2SourceVoice** voice ) +{ + if ( !wfx ) + throw std::exception( "Wave format is required\n" ); + + // No need to call IsValid on wfx because CreateSourceVoice will do that + + if ( !voice ) + throw std::exception("Voice pointer must be non-null"); + + *voice = nullptr; + + if ( !xaudio2 || mCriticalError ) + return; + +#ifndef NDEBUG + float maxFrequencyRatio = XAudio2SemitonesToFrequencyRatio(12); + assert( maxFrequencyRatio <= XAUDIO2_DEFAULT_FREQ_RATIO ); +#endif + + unsigned int voiceKey = 0; + if ( oneshot ) + { + if ( flags & ( SoundEffectInstance_Use3D | SoundEffectInstance_ReverbUseFilters | SoundEffectInstance_NoSetPitch ) ) + { + DebugTrace( ( flags & SoundEffectInstance_NoSetPitch ) + ? "ERROR: One-shot voices must support pitch-shifting for voice reuse\n" + : "ERROR: One-use voices cannot use 3D positional audio\n" ); + throw std::exception( "Invalid flags for one-shot voice" ); + } + +#ifdef VERBOSE_TRACE + if ( wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) + { + DebugTrace( "INFO: Requesting one-shot: Format Tag EXTENSIBLE %u, %u channels, %u-bit, %u blkalign, %u Hz\n", GetFormatTag( wfx ), + wfx->nChannels, wfx->wBitsPerSample, wfx->nBlockAlign, wfx->nSamplesPerSec ); + } + else + { + DebugTrace( "INFO: Requesting one-shot: Format Tag %u, %u channels, %u-bit, %u blkalign, %u Hz\n", wfx->wFormatTag, + wfx->nChannels, wfx->wBitsPerSample, wfx->nBlockAlign, wfx->nSamplesPerSec ); + } +#endif + + if ( !( mEngineFlags & AudioEngine_DisableVoiceReuse ) ) + { + voiceKey = makeVoiceKey( wfx ); + if ( voiceKey != 0 ) + { + auto it = mVoicePool.find( voiceKey ); + if ( it != mVoicePool.end() ) + { + // Found a matching (stopped) voice to reuse + assert( it->second != 0 ); + *voice = it->second; + mVoicePool.erase( it ); + + // Reset any volume/pitch-shifting + HRESULT hr = (*voice)->SetVolume(1.f); + ThrowIfFailed( hr ); + + hr = (*voice)->SetFrequencyRatio(1.f); + ThrowIfFailed( hr ); + + if (wfx->nChannels == 1 || wfx->nChannels == 2) + { + // Reset any panning + float matrix[16] = {}; + ComputePan( 0.f, wfx->nChannels, matrix ); + + hr = (*voice)->SetOutputMatrix(nullptr, wfx->nChannels, masterChannels, matrix); + ThrowIfFailed( hr ); + } + } + else if ( ( mVoicePool.size() + mOneShots.size() + 1 ) >= maxVoiceOneshots ) + { + DebugTrace( "WARNING: Too many one-shot voices in use (%Iu + %Iu >= %Iu); one-shot not played\n", + mVoicePool.size(), mOneShots.size() + 1, maxVoiceOneshots ); + return; + } + else + { + // makeVoiceKey already constrained the supported wfx formats to those supported for reuse + + char buff[64] = {}; + auto wfmt = reinterpret_cast( buff ); + + uint32_t tag = GetFormatTag( wfx ); + switch( tag ) + { + case WAVE_FORMAT_PCM: + CreateIntegerPCM( wfmt, defaultRate, wfx->nChannels, wfx->wBitsPerSample ); + break; + + case WAVE_FORMAT_IEEE_FLOAT: + CreateFloatPCM( wfmt, defaultRate, wfx->nChannels ); + break; + + case WAVE_FORMAT_ADPCM: + { + auto wfadpcm = reinterpret_cast( wfx ); + CreateADPCM( wfmt, 64, defaultRate, wfx->nChannels, wfadpcm->wSamplesPerBlock ); + } + break; + +#if defined(_XBOX_ONE) && defined(_TITLE) + case WAVE_FORMAT_XMA2: + CreateXMA2( wfmt, 64, defaultRate, wfx->nChannels, 65536, 2, 0 ); + break; +#endif + } + +#ifdef VERBOSE_TRACE + DebugTrace( "INFO: Allocate reuse voice: Format Tag %u, %u channels, %u-bit, %u blkalign, %u Hz\n", wfmt->wFormatTag, + wfmt->nChannels, wfmt->wBitsPerSample, wfmt->nBlockAlign, wfmt->nSamplesPerSec ); +#endif + + assert( voiceKey == makeVoiceKey( wfmt ) ); + + HRESULT hr = xaudio2->CreateSourceVoice( voice, wfmt, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &mVoiceCallback, nullptr, nullptr ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: CreateSourceVoice (reuse) failed with error %08X\n", hr ); + throw std::exception( "CreateSourceVoice" ); + } + } + + assert( *voice != 0 ); + HRESULT hr = (*voice)->SetSourceSampleRate( wfx->nSamplesPerSec ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SetSourceSampleRate failed with error %08X\n", hr ); + throw std::exception( "SetSourceSampleRate" ); + } + } + } + } + + if ( !*voice ) + { + if ( oneshot ) + { + if ( ( mVoicePool.size() + mOneShots.size() + 1 ) >= maxVoiceOneshots ) + { + DebugTrace( "WARNING: Too many one-shot voices in use (%Iu + %Iu >= %Iu); one-shot not played; see TrimVoicePool\n", + mVoicePool.size(), mOneShots.size() + 1, maxVoiceOneshots ); + return; + } + } + else if ( ( mVoiceInstances + 1 ) >= maxVoiceInstances ) + { + DebugTrace( "ERROR: Too many instance voices (%Iu >= %Iu); see TrimVoicePool\n", mVoiceInstances + 1, maxVoiceInstances ); + throw std::exception( "Too many instance voices" ); + } + + UINT32 vflags = ( flags & SoundEffectInstance_NoSetPitch ) ? XAUDIO2_VOICE_NOPITCH : 0; + + HRESULT hr; + if ( flags & SoundEffectInstance_Use3D ) + { + XAUDIO2_SEND_DESCRIPTOR sendDescriptors[2]; + sendDescriptors[0].Flags = sendDescriptors[1].Flags = (flags & SoundEffectInstance_ReverbUseFilters) ? XAUDIO2_SEND_USEFILTER : 0; + sendDescriptors[0].pOutputVoice = mMasterVoice; + sendDescriptors[1].pOutputVoice = mReverbVoice; + const XAUDIO2_VOICE_SENDS sendList = { mReverbVoice ? 2U : 1U, sendDescriptors }; + +#ifdef VERBOSE_TRACE + DebugTrace( "INFO: Allocate voice 3D: Format Tag %u, %u channels, %u-bit, %u blkalign, %u Hz\n", wfx->wFormatTag, + wfx->nChannels, wfx->wBitsPerSample, wfx->nBlockAlign, wfx->nSamplesPerSec ); +#endif + + hr = xaudio2->CreateSourceVoice( voice, wfx, vflags, XAUDIO2_DEFAULT_FREQ_RATIO, &mVoiceCallback, &sendList, nullptr ); + } + else + { +#ifdef VERBOSE_TRACE + DebugTrace( "INFO: Allocate voice: Format Tag %u, %u channels, %u-bit, %u blkalign, %u Hz\n", wfx->wFormatTag, + wfx->nChannels, wfx->wBitsPerSample, wfx->nBlockAlign, wfx->nSamplesPerSec ); +#endif + + hr = xaudio2->CreateSourceVoice( voice, wfx, vflags, XAUDIO2_DEFAULT_FREQ_RATIO, &mVoiceCallback, nullptr, nullptr ); + } + + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: CreateSourceVoice failed with error %08X\n", hr ); + throw std::exception( "CreateSourceVoice" ); + } + else if ( !oneshot ) + { + ++mVoiceInstances; + } + } + + if ( oneshot ) + { + assert( *voice != 0 ); + mOneShots.emplace_back( std::make_pair( voiceKey, *voice ) ); + } +} + + +void AudioEngine::Impl::DestroyVoice( _In_ IXAudio2SourceVoice* voice ) +{ + if ( !voice ) + return; + +#ifndef NDEBUG + for( auto it = mOneShots.cbegin(); it != mOneShots.cend(); ++it ) + { + if ( it->second == voice ) + { + DebugTrace( "ERROR: DestroyVoice should not be called for a one-shot voice\n" ); + throw std::exception( "DestroyVoice" ); + } + } + + for( auto it = mVoicePool.cbegin(); it != mVoicePool.cend(); ++it ) + { + if ( it->second == voice ) + { + DebugTrace( "ERROR: DestroyVoice should not be called for a one-shot voice; see TrimVoicePool\n" ); + throw std::exception( "DestroyVoice" ); + } + } +#endif + + assert( mVoiceInstances > 0 ); + --mVoiceInstances; + voice->DestroyVoice(); +} + + +void AudioEngine::Impl::RegisterNotify( _In_ IVoiceNotify* notify, bool usesUpdate ) +{ + assert( notify != 0 ); + mNotifyObjects.insert( notify ); + + if ( usesUpdate ) + { + mNotifyUpdates.insert( notify ); + } +} + + +void AudioEngine::Impl::UnregisterNotify( _In_ IVoiceNotify* notify, bool usesOneShots, bool usesUpdate ) +{ + assert( notify != 0 ); + mNotifyObjects.erase( notify ); + + // Check for any pending one-shots for this notification object + if ( usesOneShots ) + { + bool setevent = false; + + for( auto it = mOneShots.begin(); it != mOneShots.end(); ++it ) + { + assert( it->second != 0 ); + + XAUDIO2_VOICE_STATE state; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + it->second->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED ); +#else + it->second->GetState(&state); +#endif + + if ( state.pCurrentBufferContext == notify ) + { + it->second->Stop( 0 ); + it->second->FlushSourceBuffers(); + setevent = true; + } + } + + if (setevent) + { + // Trigger scan on next call to Update... + SetEvent( mVoiceCallback.mBufferEnd.get() ); + } + } + + if ( usesUpdate ) + { + mNotifyUpdates.erase( notify ); + } +} + + +//-------------------------------------------------------------------------------------- +// AudioEngine +//-------------------------------------------------------------------------------------- + +// Public constructor. +_Use_decl_annotations_ +AudioEngine::AudioEngine( AUDIO_ENGINE_FLAGS flags, const WAVEFORMATEX* wfx, const wchar_t* deviceId, AUDIO_STREAM_CATEGORY category ) + : pImpl(new Impl() ) +{ + HRESULT hr = pImpl->Initialize( flags, wfx, deviceId, category ); + if ( FAILED(hr) ) + { + if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) + { + if ( flags & AudioEngine_ThrowOnNoAudioHW ) + { + DebugTrace( "ERROR: AudioEngine found no default audio device\n" ); + throw std::exception( "AudioEngineNoAudioHW" ); + } + else + { + DebugTrace( "WARNING: AudioEngine found no default audio device; running in 'silent mode'\n" ); + } + } + else + { + DebugTrace( "ERROR: AudioEngine failed (%08X) to initialize using device [%ls]\n", hr, ( deviceId ) ? deviceId : L"default" ); + throw std::exception( "AudioEngine" ); + } + } +} + + +// Move constructor. +AudioEngine::AudioEngine(AudioEngine&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +AudioEngine& AudioEngine::operator= (AudioEngine&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +AudioEngine::~AudioEngine() +{ + if ( pImpl ) + { + pImpl->Shutdown(); + } +} + + +// Public methods. +bool AudioEngine::Update() +{ + return pImpl->Update(); +} + + +_Use_decl_annotations_ +bool AudioEngine::Reset( const WAVEFORMATEX* wfx, const wchar_t* deviceId ) +{ + if ( pImpl->xaudio2 ) + { + DebugTrace( "WARNING: Called Reset for active audio graph; going silent in preparation for migration\n" ); + pImpl->SetSilentMode(); + } + + HRESULT hr = pImpl->Reset( wfx, deviceId ); + if ( FAILED(hr) ) + { + if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) + { + if ( pImpl->mEngineFlags & AudioEngine_ThrowOnNoAudioHW ) + { + DebugTrace( "ERROR: AudioEngine found no default audio device on Reset\n" ); + throw std::exception( "AudioEngineNoAudioHW" ); + } + else + { + DebugTrace( "WARNING: AudioEngine found no default audio device on Reset; running in 'silent mode'\n" ); + return false; + } + } + else + { + DebugTrace( "ERROR: AudioEngine failed (%08X) to Reset using device [%ls]\n", hr, ( deviceId ) ? deviceId : L"default" ); + throw std::exception( "AudioEngine::Reset" ); + } + } + + DebugTrace( "INFO: AudioEngine Reset using device [%ls]\n", ( deviceId ) ? deviceId : L"default" ); + + return true; +} + + +void AudioEngine::Suspend() +{ + if ( !pImpl->xaudio2 ) + return; + + pImpl->xaudio2->StopEngine(); +} + + +void AudioEngine::Resume() +{ + if ( !pImpl->xaudio2 ) + return; + + HRESULT hr = pImpl->xaudio2->StartEngine(); + ThrowIfFailed( hr ); +} + + +float AudioEngine::GetMasterVolume() const +{ + return pImpl->mMasterVolume; +} + + +void AudioEngine::SetMasterVolume( float volume ) +{ + assert( volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL ); + + pImpl->mMasterVolume = volume; + + if ( pImpl->mMasterVoice ) + { + HRESULT hr = pImpl->mMasterVoice->SetVolume( volume ); + ThrowIfFailed( hr ); + } +} + + +void AudioEngine::SetReverb( AUDIO_ENGINE_REVERB reverb ) +{ + if ( reverb < 0 || reverb >= Reverb_MAX ) + throw std::out_of_range( "AudioEngine::SetReverb" ); + + if ( reverb == Reverb_Off ) + { + pImpl->SetReverb( nullptr ); + } + else + { + XAUDIO2FX_REVERB_PARAMETERS native; + ReverbConvertI3DL2ToNative( &gReverbPresets[ reverb ], &native ); + pImpl->SetReverb( &native ); + } +} + + +_Use_decl_annotations_ +void AudioEngine::SetReverb( const XAUDIO2FX_REVERB_PARAMETERS* native ) +{ + pImpl->SetReverb( native ); +} + + +void AudioEngine::SetMasteringLimit( int release, int loudness ) +{ + pImpl->SetMasteringLimit( release, loudness ); +} + + +// Public accessors. +AudioStatistics AudioEngine::GetStatistics() const +{ + return pImpl->GetStatistics(); +} + + +WAVEFORMATEXTENSIBLE AudioEngine::GetOutputFormat() const +{ + WAVEFORMATEXTENSIBLE wfx = {}; + + if ( !pImpl->xaudio2 ) + return wfx; + + wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wfx.Format.wBitsPerSample = wfx.Samples.wValidBitsPerSample = 16; // This is a guess + wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + + wfx.Format.nChannels = static_cast( pImpl->masterChannels ); + wfx.Format.nSamplesPerSec = pImpl->masterRate; + wfx.dwChannelMask = pImpl->masterChannelMask; + + wfx.Format.nBlockAlign = WORD( wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8 ); + wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; + + static const GUID s_pcm = { WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }; + memcpy( &wfx.SubFormat, &s_pcm, sizeof(GUID) ); + + return wfx; +} + + +uint32_t AudioEngine::GetChannelMask() const +{ + return pImpl->masterChannelMask; +} + + +int AudioEngine::GetOutputChannels() const +{ + return pImpl->masterChannels; +} + + +bool AudioEngine::IsAudioDevicePresent() const +{ + return ( pImpl->xaudio2.Get() != 0 ) && !pImpl->mCriticalError; +} + + +bool AudioEngine::IsCriticalError() const +{ + return pImpl->mCriticalError; +} + + +// Voice management. +void AudioEngine::SetDefaultSampleRate( int sampleRate ) +{ + if ( ( sampleRate < XAUDIO2_MIN_SAMPLE_RATE ) || ( sampleRate > XAUDIO2_MAX_SAMPLE_RATE ) ) + throw std::exception( "Default sample rate is out of range" ); + + pImpl->defaultRate = sampleRate; +} + + +void AudioEngine::SetMaxVoicePool( size_t maxOneShots, size_t maxInstances ) +{ + if ( maxOneShots > 0 ) + pImpl->maxVoiceOneshots = maxOneShots; + + if ( maxInstances > 0 ) + pImpl->maxVoiceInstances = maxInstances; +} + + +void AudioEngine::TrimVoicePool() +{ + pImpl->TrimVoicePool(); +} + + +_Use_decl_annotations_ +void AudioEngine::AllocateVoice( const WAVEFORMATEX* wfx, SOUND_EFFECT_INSTANCE_FLAGS flags, bool oneshot, IXAudio2SourceVoice** voice ) +{ + pImpl->AllocateVoice( wfx, flags, oneshot, voice ); +} + + +void AudioEngine::DestroyVoice( _In_ IXAudio2SourceVoice* voice ) +{ + pImpl->DestroyVoice( voice ); +} + + +void AudioEngine::RegisterNotify( _In_ IVoiceNotify* notify, bool usesUpdate ) +{ + pImpl->RegisterNotify( notify, usesUpdate ); +} + + +void AudioEngine::UnregisterNotify( _In_ IVoiceNotify* notify, bool oneshots, bool usesUpdate ) +{ + pImpl->UnregisterNotify( notify, oneshots, usesUpdate ); +} + + +IXAudio2* AudioEngine::GetInterface() const +{ + return pImpl->xaudio2.Get(); +} + + +IXAudio2MasteringVoice* AudioEngine::GetMasterVoice() const +{ + return pImpl->mMasterVoice; +} + + +IXAudio2SubmixVoice* AudioEngine::GetReverbVoice() const +{ + return pImpl->mReverbVoice; +} + + +X3DAUDIO_HANDLE& AudioEngine::Get3DHandle() const +{ + return pImpl->mX3DAudio; +} + + +// Static methods. +#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP +#include +#elif defined(_XBOX_ONE) +#include +#include +#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN8) +#pragma comment(lib,"runtimeobject.lib") +#include +#include +#endif + +std::vector AudioEngine::GetRendererDetails() +{ + std::vector list; + +#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP + + LPCWSTR id = GetDefaultAudioRenderId( Default ); + if ( !id ) + return list; + + RendererDetail device; + device.deviceId = id; + device.description = L"Default"; + + CoTaskMemFree( (LPVOID)id ); + +#elif defined(_XBOX_ONE) + + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::Foundation; + using namespace ABI::Windows::Media::Devices; + + ComPtr mdStatics; + HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mdStatics ); + ThrowIfFailed( hr ); + + HString id; + hr = mdStatics->GetDefaultAudioRenderId( AudioDeviceRole_Default, id.GetAddressOf() ); + ThrowIfFailed( hr ); + + RendererDetail device; + device.deviceId = id.GetRawBuffer( nullptr ); + device.description = L"Default"; + list.emplace_back( device ); + +#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + +#if defined(__cplusplus_winrt) + + // Enumerating with WinRT using C++/CX (Windows Store apps) + using Windows::Devices::Enumeration::DeviceClass; + using Windows::Devices::Enumeration::DeviceInformation; + using Windows::Devices::Enumeration::DeviceInformationCollection; + + auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender); + while (operation->Status != Windows::Foundation::AsyncStatus::Completed) + ; + + DeviceInformationCollection^ devices = operation->GetResults(); + + for (unsigned i = 0; i < devices->Size; ++i) + { + using Windows::Devices::Enumeration::DeviceInformation; + + DeviceInformation^ d = devices->GetAt(i); + + RendererDetail device; + device.deviceId = d->Id->Data(); + device.description = d->Name->Data(); + list.emplace_back(device); + } +#else + + // Enumerating with WinRT using WRL (Win32 desktop app for Windows 8.x) + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::Foundation; + using namespace ABI::Windows::Foundation::Collections; + using namespace ABI::Windows::Devices::Enumeration; + + RoInitializeWrapper initialize(RO_INIT_MULTITHREADED); + HRESULT hr = initialize; + ThrowIfFailed( hr ); + + ComPtr diFactory; + hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &diFactory ); + ThrowIfFailed( hr ); + + Event findCompleted( CreateEventEx( nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS ) ); + if ( !findCompleted.IsValid() ) + throw std::exception( "CreateEventEx" ); + + auto callback = Callback>( + [&findCompleted,list]( IAsyncOperation* aDevices, AsyncStatus status ) -> HRESULT + { + UNREFERENCED_PARAMETER(aDevices); + UNREFERENCED_PARAMETER(status); + SetEvent( findCompleted.Get() ); + return S_OK; + }); + + ComPtr> operation; + hr = diFactory->FindAllAsyncDeviceClass( DeviceClass_AudioRender, operation.GetAddressOf() ); + ThrowIfFailed( hr ); + + operation->put_Completed( callback.Get() ); + + (void)WaitForSingleObjectEx( findCompleted.Get(), INFINITE, FALSE ); + + ComPtr> devices; + operation->GetResults( devices.GetAddressOf() ); + + unsigned int count = 0; + hr = devices->get_Size( &count ); + ThrowIfFailed( hr ); + + if ( !count ) + return list; + + for( unsigned int j = 0; j < count; ++j ) + { + ComPtr deviceInfo; + hr = devices->GetAt( j, deviceInfo.GetAddressOf() ); + if ( SUCCEEDED(hr) ) + { + HString id; + deviceInfo->get_Id( id.GetAddressOf() ); + + HString name; + deviceInfo->get_Name( name.GetAddressOf() ); + + RendererDetail device; + device.deviceId = id.GetRawBuffer( nullptr ); + device.description = name.GetRawBuffer( nullptr ); + list.emplace_back( device ); + } + } + +#endif + +#else // _WIN32_WINNT < _WIN32_WINNT_WIN8 + + // Enumerating with XAudio 2.7 + ComPtr pXAudio2; + + HRESULT hr = XAudio2Create( pXAudio2.GetAddressOf() ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: XAudio 2.7 not found (have you called CoInitialize?)\n"); + throw std::exception( "XAudio2Create" ); + } + + UINT32 count = 0; + hr = pXAudio2->GetDeviceCount( &count ); + ThrowIfFailed(hr); + + if ( !count ) + return list; + + list.reserve( count ); + + for( UINT32 j = 0; j < count; ++j ) + { + XAUDIO2_DEVICE_DETAILS details; + hr = pXAudio2->GetDeviceDetails( j, &details ); + if ( SUCCEEDED(hr) ) + { + RendererDetail device; + device.deviceId = details.DeviceID; + device.description = details.DisplayName; + list.emplace_back( device ); + } + } + +#endif + + return list; +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Audio/DynamicSoundEffectInstance.cpp b/Kits/DirectXTK12/Audio/DynamicSoundEffectInstance.cpp new file mode 100644 index 00000000..f497fc1b --- /dev/null +++ b/Kits/DirectXTK12/Audio/DynamicSoundEffectInstance.cpp @@ -0,0 +1,376 @@ +//-------------------------------------------------------------------------------------- +// File: DynamicSoundEffectInstance.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SoundCommon.h" + +using namespace DirectX; + + +//====================================================================================== +// DynamicSoundEffectInstance +//====================================================================================== + +// Internal object implementation class. +class DynamicSoundEffectInstance::Impl : public IVoiceNotify +{ +public: + Impl( _In_ AudioEngine* engine, + _In_ DynamicSoundEffectInstance* object, _In_opt_ std::function bufferNeeded, + int sampleRate, int channels, int sampleBits, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + mBase(), + mBufferNeeded( nullptr ), + mObject( object ) + { + if ( ( sampleRate < XAUDIO2_MIN_SAMPLE_RATE ) + || ( sampleRate > XAUDIO2_MAX_SAMPLE_RATE ) ) + { + DebugTrace( "DynamicSoundEffectInstance sampleRate must be in range %u...%u\n", XAUDIO2_MIN_SAMPLE_RATE, XAUDIO2_MAX_SAMPLE_RATE ); + throw std::invalid_argument( "DynamicSoundEffectInstance" ); + } + + if ( !channels || ( channels > 8 ) ) + { + DebugTrace( "DynamicSoundEffectInstance channels must be in range 1...8\n" ); + throw std::invalid_argument( "DynamicSoundEffectInstance" ); + } + + switch ( sampleBits ) + { + case 8: + case 16: + break; + + default: + DebugTrace( "DynamicSoundEffectInstance sampleBits must be 8-bit or 16-bit\n" ); + throw std::invalid_argument( "DynamicSoundEffectInstance" ); + } + + mBufferEvent.reset( CreateEventEx( nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !mBufferEvent ) + { + throw std::exception( "CreateEvent" ); + } + + CreateIntegerPCM( &mWaveFormat, sampleRate, channels, sampleBits ); + + assert( engine != 0 ); + engine->RegisterNotify( this, true ); + + mBase.Initialize( engine, &mWaveFormat, flags ); + + mBufferNeeded = bufferNeeded; + } + + virtual ~Impl() + { + mBase.DestroyVoice(); + + if ( mBase.engine ) + { + mBase.engine->UnregisterNotify( this, false, true ); + mBase.engine = nullptr; + } + } + + void Play(); + + void Resume(); + + void SubmitBuffer( _In_reads_bytes_(audioBytes) const uint8_t* pAudioData, uint32_t offset, size_t audioBytes ); + + const WAVEFORMATEX* GetFormat() const { return &mWaveFormat; } ; + + // IVoiceNotify + virtual void __cdecl OnBufferEnd() override + { + SetEvent( mBufferEvent.get() ); + } + + virtual void __cdecl OnCriticalError() override + { + mBase.OnCriticalError(); + } + + virtual void __cdecl OnReset() override + { + mBase.OnReset(); + } + + virtual void __cdecl OnUpdate() override; + + virtual void __cdecl OnDestroyEngine() override + { + mBase.OnDestroy(); + } + + virtual void __cdecl OnTrim() override + { + mBase.OnTrim(); + } + + virtual void __cdecl GatherStatistics( AudioStatistics& stats ) const override + { + mBase.GatherStatistics(stats); + } + + SoundEffectInstanceBase mBase; + +private: + ScopedHandle mBufferEvent; + std::function mBufferNeeded; + DynamicSoundEffectInstance* mObject; + WAVEFORMATEX mWaveFormat; +}; + + +void DynamicSoundEffectInstance::Impl::Play() +{ + if ( !mBase.voice ) + { + mBase.AllocateVoice( &mWaveFormat ); + } + + (void)mBase.Play(); + + if ( mBase.voice && ( mBase.state == PLAYING ) && ( mBase.GetPendingBufferCount() <= 2 ) ) + { + SetEvent( mBufferEvent.get() ); + } +} + + +void DynamicSoundEffectInstance::Impl::Resume() +{ + if ( mBase.voice && ( mBase.state == PAUSED ) ) + { + mBase.Resume(); + + if ( ( mBase.state == PLAYING ) && ( mBase.GetPendingBufferCount() <= 2 ) ) + { + SetEvent( mBufferEvent.get() ); + } + } +} + + +_Use_decl_annotations_ +void DynamicSoundEffectInstance::Impl::SubmitBuffer( const uint8_t* pAudioData, uint32_t offset, size_t audioBytes ) +{ + if ( !pAudioData || !audioBytes ) + throw std::exception( "Invalid audio data buffer" ); + +#ifdef _M_X64 + if ( audioBytes > 0xFFFFFFFF ) + throw std::out_of_range( "SubmitBuffer" ); +#endif + + XAUDIO2_BUFFER buffer = {}; + buffer.AudioBytes = static_cast( audioBytes ); + buffer.pAudioData = pAudioData; + + if( offset ) + { + assert( mWaveFormat.wFormatTag == WAVE_FORMAT_PCM ); + buffer.PlayBegin = offset / mWaveFormat.nBlockAlign; + buffer.PlayLength = static_cast( ( audioBytes - offset ) / mWaveFormat.nBlockAlign ); + } + + buffer.pContext = this; + + HRESULT hr = mBase.voice->SubmitSourceBuffer( &buffer, nullptr ); + if ( FAILED(hr) ) + { +#ifdef _DEBUG + DebugTrace( "ERROR: DynamicSoundEffectInstance failed (%08X) when submitting buffer:\n", hr ); + + DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %Iu bytes [%u offset)\n", mWaveFormat.wFormatTag, + mWaveFormat.nChannels, mWaveFormat.wBitsPerSample, mWaveFormat.nSamplesPerSec, audioBytes, offset ); +#endif + throw std::exception( "SubmitSourceBuffer" ); + } +} + + +void DynamicSoundEffectInstance::Impl::OnUpdate() +{ + DWORD result = WaitForSingleObjectEx( mBufferEvent.get(), 0, FALSE ); + switch( result ) + { + case WAIT_TIMEOUT: + break; + + case WAIT_OBJECT_0: + if( mBufferNeeded ) + { + // This callback happens on the same thread that called AudioEngine::Update() + mBufferNeeded( mObject ); + } + break; + + case WAIT_FAILED: + throw std::exception( "WaitForSingleObjectEx" ); + } +} + + + +//-------------------------------------------------------------------------------------- +// DynamicSoundEffectInstance +//-------------------------------------------------------------------------------------- + +#pragma warning( disable : 4355 ) + +// Public constructors +_Use_decl_annotations_ +DynamicSoundEffectInstance::DynamicSoundEffectInstance( AudioEngine* engine, + std::function bufferNeeded, + int sampleRate, int channels, int sampleBits, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + pImpl( new Impl( engine, this, bufferNeeded, sampleRate, channels, sampleBits, flags ) ) +{ +} + + +// Move constructor. +DynamicSoundEffectInstance::DynamicSoundEffectInstance(DynamicSoundEffectInstance&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +DynamicSoundEffectInstance& DynamicSoundEffectInstance::operator= (DynamicSoundEffectInstance&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +DynamicSoundEffectInstance::~DynamicSoundEffectInstance() +{ +} + + +// Public methods. +void DynamicSoundEffectInstance::Play() +{ + pImpl->Play(); +} + + +void DynamicSoundEffectInstance::Stop( bool immediate ) +{ + bool looped = false; + pImpl->mBase.Stop( immediate, looped ); +} + + +void DynamicSoundEffectInstance::Pause() +{ + pImpl->mBase.Pause(); +} + + +void DynamicSoundEffectInstance::Resume() +{ + pImpl->Resume(); +} + + +void DynamicSoundEffectInstance::SetVolume( float volume ) +{ + pImpl->mBase.SetVolume( volume ); +} + + +void DynamicSoundEffectInstance::SetPitch( float pitch ) +{ + pImpl->mBase.SetPitch( pitch ); +} + + +void DynamicSoundEffectInstance::SetPan( float pan ) +{ + pImpl->mBase.SetPan( pan ); +} + + +void DynamicSoundEffectInstance::Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords ) +{ + pImpl->mBase.Apply3D( listener, emitter, rhcoords ); +} + + +_Use_decl_annotations_ +void DynamicSoundEffectInstance::SubmitBuffer( const uint8_t* pAudioData, size_t audioBytes ) +{ + pImpl->SubmitBuffer( pAudioData, 0, audioBytes ); +} + + +_Use_decl_annotations_ +void DynamicSoundEffectInstance::SubmitBuffer( const uint8_t* pAudioData, uint32_t offset, size_t audioBytes ) +{ + pImpl->SubmitBuffer( pAudioData, offset, audioBytes ); +} + + +// Public accessors. +SoundState DynamicSoundEffectInstance::GetState() +{ + return pImpl->mBase.GetState( false ); +} + + +size_t DynamicSoundEffectInstance::GetSampleDuration( size_t bytes ) const +{ + auto wfx = pImpl->GetFormat(); + if ( !wfx || !wfx->wBitsPerSample || !wfx->nChannels ) + return 0; + + return static_cast( ( uint64_t( bytes ) * 8 ) + / uint64_t( wfx->wBitsPerSample * wfx->nChannels ) ); +} + + +size_t DynamicSoundEffectInstance::GetSampleDurationMS( size_t bytes ) const +{ + auto wfx = pImpl->GetFormat(); + if ( !wfx || !wfx->nAvgBytesPerSec ) + return 0; + + return static_cast( ( uint64_t(bytes) * 1000 ) / wfx->nAvgBytesPerSec ); +} + + +size_t DynamicSoundEffectInstance::GetSampleSizeInBytes( uint64_t duration ) const +{ + auto wfx = pImpl->GetFormat(); + if ( !wfx || !wfx->nSamplesPerSec ) + return 0; + + return static_cast( ( ( duration * wfx->nSamplesPerSec ) / 1000 ) * wfx->nBlockAlign ); +} + + +int DynamicSoundEffectInstance::GetPendingBufferCount() const +{ + return pImpl->mBase.GetPendingBufferCount(); +} + + +const WAVEFORMATEX* DynamicSoundEffectInstance::GetFormat() const +{ + return pImpl->GetFormat(); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Audio/SoundCommon.cpp b/Kits/DirectXTK12/Audio/SoundCommon.cpp new file mode 100644 index 00000000..3b32d648 --- /dev/null +++ b/Kits/DirectXTK12/Audio/SoundCommon.cpp @@ -0,0 +1,787 @@ +//-------------------------------------------------------------------------------------- +// File: SoundCommon.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "pch.h" +#include "SoundCommon.h" + +using namespace DirectX; + + +namespace +{ + template WORD ChannelsSpecifiedInMask(T x) + { + WORD bitCount = 0; + while (x) {++bitCount; x &= (x-1);} + return bitCount; + } +} + + +//====================================================================================== +// Wave format utilities +//====================================================================================== + +bool DirectX::IsValid( _In_ const WAVEFORMATEX* wfx ) +{ + if ( !wfx ) + return false; + + if ( !wfx->nChannels ) + { + DebugTrace( "ERROR: Wave format must have at least 1 channel\n" ); + return false; + } + + if ( wfx->nChannels > XAUDIO2_MAX_AUDIO_CHANNELS ) + { + DebugTrace( "ERROR: Wave format must have less than %u channels (%u)\n", XAUDIO2_MAX_AUDIO_CHANNELS, wfx->nChannels ); + return false; + } + + if ( !wfx->nSamplesPerSec ) + { + DebugTrace( "ERROR: Wave format cannot have a sample rate of 0\n" ); + return false; + } + + if ( ( wfx->nSamplesPerSec < XAUDIO2_MIN_SAMPLE_RATE ) + || ( wfx->nSamplesPerSec > XAUDIO2_MAX_SAMPLE_RATE ) ) + { + DebugTrace( "ERROR: Wave format channel count must be in range %u..%u (%u)\n", XAUDIO2_MIN_SAMPLE_RATE, XAUDIO2_MAX_SAMPLE_RATE, wfx->nSamplesPerSec ); + return false; + } + + switch ( wfx->wFormatTag ) + { + case WAVE_FORMAT_PCM: + + switch( wfx->wBitsPerSample ) + { + case 8: + case 16: + case 24: + case 32: + break; + + default: + DebugTrace( "ERROR: Wave format integer PCM must have 8, 16, 24, or 32 bits per sample (%u)\n", wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nBlockAlign != ( wfx->nChannels * wfx->wBitsPerSample / 8 ) ) + { + DebugTrace( "ERROR: Wave format integer PCM - nBlockAlign (%u) != nChannels (%u) * wBitsPerSample (%u) / 8\n", + wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nAvgBytesPerSec != ( wfx->nSamplesPerSec * wfx->nBlockAlign ) ) + { + DebugTrace( "ERROR: Wave format integer PCM - nAvgBytesPerSec (%lu) != nSamplesPerSec (%lu) * nBlockAlign (%u)\n", + wfx->nAvgBytesPerSec, wfx->nSamplesPerSec, wfx->nBlockAlign ); + return false; + } + + return true; + + case WAVE_FORMAT_IEEE_FLOAT: + + if ( wfx->wBitsPerSample != 32 ) + { + DebugTrace( "ERROR: Wave format float PCM must have 32-bits per sample (%u)\n", wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nBlockAlign != ( wfx->nChannels * wfx->wBitsPerSample / 8 ) ) + { + DebugTrace( "ERROR: Wave format float PCM - nBlockAlign (%u) != nChannels (%u) * wBitsPerSample (%u) / 8\n", + wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nAvgBytesPerSec != ( wfx->nSamplesPerSec * wfx->nBlockAlign ) ) + { + DebugTrace( "ERROR: Wave format float PCM - nAvgBytesPerSec (%lu) != nSamplesPerSec (%lu) * nBlockAlign (%u)\n", + wfx->nAvgBytesPerSec, wfx->nSamplesPerSec, wfx->nBlockAlign ); + return false; + } + + return true; + + case WAVE_FORMAT_ADPCM: + + if ( ( wfx->nChannels != 1 ) && ( wfx->nChannels != 2 ) ) + { + DebugTrace( "ERROR: Wave format ADPCM must have 1 or 2 channels (%u)\n", wfx->nChannels ); + return false; + } + + if ( wfx->wBitsPerSample != 4 /*MSADPCM_BITS_PER_SAMPLE*/ ) + { + DebugTrace( "ERROR: Wave format ADPCM must have 4 bits per sample (%u)\n", wfx->wBitsPerSample ); + return false; + } + + if ( wfx->cbSize != 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/ ) + { + DebugTrace( "ERROR: Wave format ADPCM must have cbSize = 32 (%u)\n", wfx->cbSize ); + return false; + } + else + { + auto wfadpcm = reinterpret_cast( wfx ); + + if ( wfadpcm->wNumCoef != 7 /*MSADPCM_NUM_COEFFICIENTS*/ ) + { + DebugTrace( "ERROR: Wave format ADPCM must have 7 coefficients (%u)\n", wfadpcm->wNumCoef ); + return false; + } + + bool valid = true; + for ( int j = 0; j < 7 /*MSADPCM_NUM_COEFFICIENTS*/; ++j ) + { + // Microsoft ADPCM standard encoding coefficients + static const short g_pAdpcmCoefficients1[] = {256, 512, 0, 192, 240, 460, 392}; + static const short g_pAdpcmCoefficients2[] = { 0, -256, 0, 64, 0, -208, -232}; + + if ( wfadpcm->aCoef[j].iCoef1 != g_pAdpcmCoefficients1[j] + || wfadpcm->aCoef[j].iCoef2 != g_pAdpcmCoefficients2[j] ) + { + valid = false; + } + } + + if ( !valid ) + { + DebugTrace( "ERROR: Wave formt ADPCM found non-standard coefficients\n" ); + return false; + } + + if ( ( wfadpcm->wSamplesPerBlock < 4 /*MSADPCM_MIN_SAMPLES_PER_BLOCK*/ ) + || ( wfadpcm->wSamplesPerBlock > 64000 /*MSADPCM_MAX_SAMPLES_PER_BLOCK*/ ) ) + { + DebugTrace( "ERROR: Wave format ADPCM wSamplesPerBlock must be 4..64000 (%u)\n", wfadpcm->wSamplesPerBlock ); + return false; + } + + if ( wfadpcm->wfx.nChannels == 1 && ( wfadpcm->wSamplesPerBlock % 2 ) ) + { + DebugTrace( "ERROR: Wave format ADPCM mono files must have even wSamplesPerBlock\n" ); + return false; + } + + int nHeaderBytes = 7 /*MSADPCM_HEADER_LENGTH*/ * wfx->nChannels; + int nBitsPerFrame = 4 /*MSADPCM_BITS_PER_SAMPLE*/ * wfx->nChannels; + int nPcmFramesPerBlock = (wfx->nBlockAlign - nHeaderBytes) * 8 / nBitsPerFrame + 2; + + if ( wfadpcm->wSamplesPerBlock != nPcmFramesPerBlock ) + { + DebugTrace( "ERROR: Wave format ADPCM %u-channel with nBlockAlign = %u must have wSamplesPerBlock = %u (%u)\n", + wfx->nChannels, wfx->nBlockAlign, nPcmFramesPerBlock, wfadpcm->wSamplesPerBlock ); + return false; + } + } + return true; + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + if ( wfx->wBitsPerSample != 16 ) + { + DebugTrace( "ERROR: Wave format xWMA only supports 16-bit data\n" ); + return false; + } + + if ( !wfx->nBlockAlign ) + { + DebugTrace( "ERROR: Wave format xWMA must have a non-zero nBlockAlign\n" ); + return false; + } + + if ( !wfx->nAvgBytesPerSec ) + { + DebugTrace( "ERROR: Wave format xWMA must have a non-zero nAvgBytesPerSec\n" ); + return false; + } + + return true; + +#else + DebugTrace( "ERROR: Wave format xWMA not supported by this version of DirectXTK for Audio\n" ); + return false; +#endif + + case 0x166 /* WAVE_FORMAT_XMA2 */: + +#if defined(_XBOX_ONE) && defined(_TITLE) + + if ( wfx->nBlockAlign != wfx->nChannels * XMA_OUTPUT_SAMPLE_BYTES) + { + DebugTrace( "ERROR: Wave format XMA2 - nBlockAlign (%u) != nChannels(%u) * %u\n", wfx->nBlockAlign, wfx->nChannels, XMA_OUTPUT_SAMPLE_BYTES ); + return false; + } + + if ( wfx->wBitsPerSample != XMA_OUTPUT_SAMPLE_BITS ) + { + DebugTrace( "ERROR: Wave format XMA2 wBitsPerSample (%u) should be %u\n", wfx->wBitsPerSample, XMA_OUTPUT_SAMPLE_BITS ); + return false; + } + + if ( wfx->cbSize != ( sizeof(XMA2WAVEFORMATEX) - sizeof(WAVEFORMATEX) ) ) + { + DebugTrace( "ERROR: Wave format XMA2 - cbSize must be %Iu (%u)\n", ( sizeof(XMA2WAVEFORMATEX) - sizeof(WAVEFORMATEX) ), wfx->cbSize ); + return false; + } + else + { + auto xmaFmt = reinterpret_cast( wfx ); + + if ( xmaFmt->EncoderVersion < 3 ) + { + DebugTrace( "ERROR: Wave format XMA2 encoder version (%u) - 3 or higher is required\n", xmaFmt->EncoderVersion ); + return false; + } + + if ( !xmaFmt->BlockCount ) + { + DebugTrace( "ERROR: Wave format XMA2 BlockCount must be non-zero\n" ); + return false; + } + + if ( !xmaFmt->BytesPerBlock || ( xmaFmt->BytesPerBlock > XMA_READBUFFER_MAX_BYTES ) ) + { + DebugTrace( "ERROR: Wave format XMA2 BytesPerBlock (%u) is invalid\n", xmaFmt->BytesPerBlock ); + return false; + } + + if ( xmaFmt->ChannelMask ) + { + auto channelBits = ChannelsSpecifiedInMask( xmaFmt->ChannelMask ); + if ( channelBits != wfx->nChannels ) + { + DebugTrace( "ERROR: Wave format XMA2 - nChannels=%u but ChannelMask (%08X) has %u bits set\n", + xmaFmt->ChannelMask, wfx->nChannels, channelBits ); + return false; + } + } + + if ( xmaFmt->NumStreams != ( ( wfx->nChannels + 1) / 2 ) ) + { + DebugTrace( "ERROR: Wave format XMA2 - NumStreams (%u) != ( nChannels(%u) + 1 ) / 2\n", xmaFmt->NumStreams, wfx->nChannels ); + return false; + } + + if ( ( xmaFmt->PlayBegin + xmaFmt->PlayLength ) > xmaFmt->SamplesEncoded ) + { + DebugTrace( "ERROR: Wave format XMA2 play region too large (%u + %u > %u)\n", xmaFmt->PlayBegin, xmaFmt->PlayLength, xmaFmt->SamplesEncoded ); + return false; + } + + if ( ( xmaFmt->LoopBegin + xmaFmt->LoopLength ) > xmaFmt->SamplesEncoded ) + { + DebugTrace( "ERROR: Wave format XMA2 loop region too large (%u + %u > %u)\n", xmaFmt->LoopBegin, xmaFmt->LoopLength, xmaFmt->SamplesEncoded ); + return false; + } + } + return true; + +#else + DebugTrace( "ERROR: Wave format XMA2 not supported by this version of DirectXTK for Audio\n" ); + return false; +#endif + + case WAVE_FORMAT_EXTENSIBLE: + if ( wfx->cbSize < ( sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) ) ) + { + DebugTrace( "ERROR: Wave format WAVE_FORMAT_EXTENSIBLE - cbSize must be %Iu (%u)\n", ( sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) ), wfx->cbSize ); + return false; + } + else + { + static const GUID s_wfexBase = {0x00000000, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; + + auto wfex = reinterpret_cast( wfx ); + + if ( memcmp( reinterpret_cast(&wfex->SubFormat) + sizeof(DWORD), + reinterpret_cast(&s_wfexBase) + sizeof(DWORD), sizeof(GUID) - sizeof(DWORD) ) != 0 ) + { + DebugTrace( "ERROR: Wave format WAVEFORMATEXTENSIBLE encountered with unknown GUID ({%8.8lX-%4.4X-%4.4X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X})\n", + wfex->SubFormat.Data1, wfex->SubFormat.Data2, wfex->SubFormat.Data3, + wfex->SubFormat.Data4[0], wfex->SubFormat.Data4[1], wfex->SubFormat.Data4[2], wfex->SubFormat.Data4[3], + wfex->SubFormat.Data4[4], wfex->SubFormat.Data4[5], wfex->SubFormat.Data4[6], wfex->SubFormat.Data4[7] ); + return false; + } + + switch( wfex->SubFormat.Data1 ) + { + case WAVE_FORMAT_PCM: + + switch( wfx->wBitsPerSample ) + { + case 8: + case 16: + case 24: + case 32: + break; + + default: + DebugTrace( "ERROR: Wave format integer PCM must have 8, 16, 24, or 32 bits per sample (%u)\n", wfx->wBitsPerSample ); + return false; + } + + switch( wfex->Samples.wValidBitsPerSample ) + { + case 0: + case 8: + case 16: + case 20: + case 24: + case 32: + break; + + default: + DebugTrace( "ERROR: Wave format integer PCM must have 8, 16, 20, 24, or 32 valid bits per sample (%u)\n", wfex->Samples.wValidBitsPerSample ); + return false; + } + + if ( wfex->Samples.wValidBitsPerSample + && ( wfex->Samples.wValidBitsPerSample > wfx->wBitsPerSample ) ) + { + DebugTrace( "ERROR: Wave format ingter PCM wValidBitsPerSample (%u) is greater than wBitsPerSample (%u)\n", wfex->Samples.wValidBitsPerSample, wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nBlockAlign != ( wfx->nChannels * wfx->wBitsPerSample / 8 ) ) + { + DebugTrace( "ERROR: Wave format integer PCM - nBlockAlign (%u) != nChannels (%u) * wBitsPerSample (%u) / 8\n", + wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nAvgBytesPerSec != ( wfx->nSamplesPerSec * wfx->nBlockAlign ) ) + { + DebugTrace( "ERROR: Wave format integer PCM - nAvgBytesPerSec (%lu) != nSamplesPerSec (%lu) * nBlockAlign (%u)\n", + wfx->nAvgBytesPerSec, wfx->nSamplesPerSec, wfx->nBlockAlign ); + return false; + } + + break; + + case WAVE_FORMAT_IEEE_FLOAT: + + if ( wfx->wBitsPerSample != 32 ) + { + DebugTrace( "ERROR: Wave format float PCM must have 32-bits per sample (%u)\n", wfx->wBitsPerSample ); + return false; + } + + switch( wfex->Samples.wValidBitsPerSample ) + { + case 0: + case 32: + break; + + default: + DebugTrace( "ERROR: Wave format float PCM must have 32 valid bits per sample (%u)\n", wfex->Samples.wValidBitsPerSample ); + return false; + } + + if ( wfx->nBlockAlign != ( wfx->nChannels * wfx->wBitsPerSample / 8 ) ) + { + DebugTrace( "ERROR: Wave format float PCM - nBlockAlign (%u) != nChannels (%u) * wBitsPerSample (%u) / 8\n", + wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample ); + return false; + } + + if ( wfx->nAvgBytesPerSec != ( wfx->nSamplesPerSec * wfx->nBlockAlign ) ) + { + DebugTrace( "ERROR: Wave format float PCM - nAvgBytesPerSec (%lu) != nSamplesPerSec (%lu) * nBlockAlign (%u)\n", + wfx->nAvgBytesPerSec, wfx->nSamplesPerSec, wfx->nBlockAlign ); + return false; + } + + break; + + case WAVE_FORMAT_ADPCM: + DebugTrace( "ERROR: Wave format ADPCM is not supported as a WAVEFORMATEXTENSIBLE\n" ); + return false; + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + if ( wfx->wBitsPerSample != 16 ) + { + DebugTrace( "ERROR: Wave format xWMA only supports 16-bit data\n" ); + return false; + } + + if ( !wfx->nBlockAlign ) + { + DebugTrace( "ERROR: Wave format xWMA must have a non-zero nBlockAlign\n" ); + return false; + } + + if ( !wfx->nAvgBytesPerSec ) + { + DebugTrace( "ERROR: Wave format xWMA must have a non-zero nAvgBytesPerSec\n" ); + return false; + } + + break; + +#else + DebugTrace( "ERROR: Wave format xWMA not supported by this version of DirectXTK for Audio\n" ); + return false; +#endif + + case 0x166 /* WAVE_FORMAT_XMA2 */: + DebugTrace( "ERROR: Wave format XMA2 is not supported as a WAVEFORMATEXTENSIBLE\n" ); + return false; + + default: + DebugTrace( "ERROR: Unknown WAVEFORMATEXTENSIBLE format tag (%u)\n", wfex->SubFormat.Data1 ); + return false; + } + + if ( wfex->dwChannelMask ) + { + auto channelBits = ChannelsSpecifiedInMask( wfex->dwChannelMask ); + if ( channelBits != wfx->nChannels ) + { + DebugTrace( "ERROR: WAVEFORMATEXTENSIBLE: nChannels=%u but ChannelMask has %u bits set\n", + wfx->nChannels, channelBits ); + return false; + } + } + + return true; + } + + default: + DebugTrace( "ERROR: Unknown WAVEFORMATEX format tag (%u)\n", wfx->wFormatTag ); + return false; + } +} + + +uint32_t DirectX::GetDefaultChannelMask( int channels ) +{ + switch( channels ) + { + case 1: return SPEAKER_MONO; + case 2: return SPEAKER_STEREO; + case 3: return SPEAKER_2POINT1; + case 4: return SPEAKER_QUAD; + case 5: return SPEAKER_4POINT1; + case 6: return SPEAKER_5POINT1; + case 7: return SPEAKER_5POINT1 | SPEAKER_BACK_CENTER; + case 8: return SPEAKER_7POINT1; + default: return 0; + } +} + + +_Use_decl_annotations_ +void DirectX::CreateIntegerPCM( WAVEFORMATEX* wfx, int sampleRate, int channels, int sampleBits ) +{ + int blockAlign = channels * sampleBits / 8; + + wfx->wFormatTag = WAVE_FORMAT_PCM; + wfx->nChannels = static_cast( channels ); + wfx->nSamplesPerSec = static_cast( sampleRate ); + wfx->nAvgBytesPerSec = static_cast( blockAlign * sampleRate ); + wfx->nBlockAlign = static_cast( blockAlign ); + wfx->wBitsPerSample = static_cast( sampleBits ); + wfx->cbSize = 0; + + assert( IsValid( wfx ) ); +} + + +_Use_decl_annotations_ +void DirectX::CreateFloatPCM( WAVEFORMATEX* wfx, int sampleRate, int channels ) +{ + int blockAlign = channels * 4; + + wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + wfx->nChannels = static_cast( channels ); + wfx->nSamplesPerSec = static_cast( sampleRate ); + wfx->nAvgBytesPerSec = static_cast( blockAlign * sampleRate ); + wfx->nBlockAlign = static_cast( blockAlign ); + wfx->wBitsPerSample = 32; + wfx->cbSize = 0; + + assert( IsValid( wfx ) ); +} + + +_Use_decl_annotations_ +void DirectX::CreateADPCM( WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int samplesPerBlock ) +{ + if ( wfxSize < ( sizeof(WAVEFORMATEX) + 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/ ) ) + { + DebugTrace( "CreateADPCM needs at least %Iu bytes for the result\n", ( sizeof(WAVEFORMATEX) + 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/ ) ); + throw std::invalid_argument( "ADPCMWAVEFORMAT" ); + } + + if ( !samplesPerBlock ) + { + DebugTrace( "CreateADPCM needs a non-zero samples per block count\n" ); + throw std::invalid_argument( "ADPCMWAVEFORMAT" ); + } + + int blockAlign = (7 /*MSADPCM_HEADER_LENGTH*/) * channels + + (samplesPerBlock - 2) * (4 /* MSADPCM_BITS_PER_SAMPLE */) * channels / 8; + + wfx->wFormatTag = WAVE_FORMAT_ADPCM; + wfx->nChannels = static_cast( channels ); + wfx->nSamplesPerSec = static_cast( sampleRate ); + wfx->nAvgBytesPerSec = static_cast( blockAlign * sampleRate / samplesPerBlock ); + wfx->nBlockAlign = static_cast( blockAlign ); + wfx->wBitsPerSample = 4 /* MSADPCM_BITS_PER_SAMPLE */; + wfx->cbSize = 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/; + + auto adpcm = reinterpret_cast( wfx ); + adpcm->wSamplesPerBlock = static_cast( samplesPerBlock ); + adpcm->wNumCoef = 7 /* MSADPCM_NUM_COEFFICIENTS */; + + static ADPCMCOEFSET aCoef[7] = { { 256, 0}, {512, -256}, {0,0}, {192,64}, {240,0}, {460, -208}, {392,-232} }; + memcpy( &adpcm->aCoef, aCoef, sizeof(aCoef) ); + + assert( IsValid( wfx ) ); +} + + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) +_Use_decl_annotations_ +void DirectX::CreateXWMA( WAVEFORMATEX* wfx, int sampleRate, int channels, int blockAlign, int avgBytes, bool wma3 ) +{ + wfx->wFormatTag = (wma3) ? WAVE_FORMAT_WMAUDIO3 : WAVE_FORMAT_WMAUDIO2; + wfx->nChannels = static_cast( channels ); + wfx->nSamplesPerSec = static_cast( sampleRate ); + wfx->nAvgBytesPerSec = static_cast( avgBytes ); + wfx->nBlockAlign = static_cast( blockAlign ); + wfx->wBitsPerSample = 16; + wfx->cbSize = 0; + + assert( IsValid( wfx ) ); +} +#endif + + +#if defined(_XBOX_ONE) && defined(_TITLE) +_Use_decl_annotations_ +void DirectX::CreateXMA2( WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int bytesPerBlock, int blockCount, int samplesEncoded ) +{ + if ( wfxSize < sizeof(XMA2WAVEFORMATEX) ) + { + DebugTrace( "XMA2 needs at least %Iu bytes for the result\n", sizeof(XMA2WAVEFORMATEX) ); + throw std::invalid_argument( "XMA2WAVEFORMATEX" ); + } + + if ( !bytesPerBlock || ( bytesPerBlock > XMA_READBUFFER_MAX_BYTES ) ) + { + DebugTrace( "XMA2 needs a valid bytes per block\n" ); + throw std::invalid_argument( "XMA2WAVEFORMATEX" ); + } + + int blockAlign = (channels * ( 16 /*XMA_OUTPUT_SAMPLE_BITS*/ ) / 8); + + wfx->wFormatTag = WAVE_FORMAT_XMA2; + wfx->nChannels = static_cast( channels ); + wfx->nSamplesPerSec = static_cast( sampleRate ); + wfx->nAvgBytesPerSec = static_cast( blockAlign * sampleRate ); + wfx->nBlockAlign = static_cast( blockAlign ); + wfx->wBitsPerSample = 16 /* XMA_OUTPUT_SAMPLE_BITS */; + wfx->cbSize = sizeof(XMA2WAVEFORMATEX) - sizeof(WAVEFORMATEX); + + auto xmaFmt = reinterpret_cast(wfx); + + xmaFmt->NumStreams = static_cast( (channels + 1) / 2 ); + + xmaFmt->ChannelMask = GetDefaultChannelMask( channels ); + + xmaFmt->SamplesEncoded = static_cast( samplesEncoded ); + xmaFmt->BytesPerBlock = bytesPerBlock; + xmaFmt->PlayBegin = xmaFmt->PlayLength = + xmaFmt->LoopBegin = xmaFmt->LoopLength = xmaFmt->LoopCount = 0; + xmaFmt->EncoderVersion = 4 /* XMAENCODER_VERSION_XMA2 */; + xmaFmt->BlockCount = static_cast( blockCount ); + + assert( IsValid( wfx ) ); +} +#endif // _XBOX_ONE && _TITLE + + +_Use_decl_annotations_ +bool DirectX::ComputePan( float pan, int channels, float* matrix ) +{ + memset( matrix, 0, sizeof(float) * 16 ); + + if (channels == 1) + { + // Mono panning + float left = ( pan >= 0 ) ? ( 1.f - pan ) : 1.f; + left = std::min( 1.f, left ); + left = std::max( -1.f, left ); + + float right = ( pan <= 0 ) ? ( - pan - 1.f ) : 1.f; + right = std::min( 1.f, right ); + right = std::max( -1.f, right ); + + matrix[0] = left; + matrix[1] = right; + } + else if (channels == 2) + { + // Stereo panning + if ( -1.f <= pan && pan <= 0.f ) + { + matrix[0] = .5f * pan + 1.f; // .5 when pan is -1, 1 when pan is 0 + matrix[1] = .5f * -pan; // .5 when pan is -1, 0 when pan is 0 + matrix[2] = 0.f; // 0 when pan is -1, 0 when pan is 0 + matrix[3] = pan + 1.f; // 0 when pan is -1, 1 when pan is 0 + } + else + { + matrix[0] = -pan + 1.f; // 1 when pan is 0, 0 when pan is 1 + matrix[1] = 0.f; // 0 when pan is 0, 0 when pan is 1 + matrix[2] = .5f * pan; // 0 when pan is 0, .5f when pan is 1 + matrix[3] = .5f * -pan + 1.f; // 1 when pan is 0. .5f when pan is 1 + } + } + else + { + if ( pan != 0.f ) + { + DebugTrace( "WARNING: Only supports panning on mono or stereo source data, ignored\n" ); + } + return false; + } + + return true; +} + + +//====================================================================================== +// SoundEffectInstanceBase +//====================================================================================== + +void SoundEffectInstanceBase::SetPan( float pan ) +{ + assert( pan >= -1.f && pan <= 1.f ); + + mPan = pan; + + if ( !voice ) + return; + + float matrix[16]; + if ( ComputePan( pan, mDSPSettings.SrcChannelCount, matrix ) ) + { + HRESULT hr = voice->SetOutputMatrix( nullptr, mDSPSettings.SrcChannelCount, mDSPSettings.DstChannelCount, matrix ); + ThrowIfFailed( hr ); + } +} + + +void SoundEffectInstanceBase::Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords ) +{ + if ( !voice ) + return; + + if ( !( mFlags & SoundEffectInstance_Use3D ) ) + { + DebugTrace( "ERROR: Apply3D called for an instance created without SoundEffectInstance_Use3D set\n" ); + throw std::exception( "Apply3D" ); + } + + DWORD dwCalcFlags = X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER | X3DAUDIO_CALCULATE_LPF_DIRECT; + + if ( mFlags & SoundEffectInstance_UseRedirectLFE ) + { + // On devices with an LFE channel, allow the mono source data to be routed to the LFE destination channel. + dwCalcFlags |= X3DAUDIO_CALCULATE_REDIRECT_TO_LFE; + } + + auto reverb = mReverbVoice; + if ( reverb ) + { + dwCalcFlags |= X3DAUDIO_CALCULATE_LPF_REVERB | X3DAUDIO_CALCULATE_REVERB; + } + + float matrix[ XAUDIO2_MAX_AUDIO_CHANNELS * 8 ]; + assert( mDSPSettings.SrcChannelCount <= XAUDIO2_MAX_AUDIO_CHANNELS ); + assert( mDSPSettings.DstChannelCount <= 8 ); + mDSPSettings.pMatrixCoefficients = matrix; + + assert( engine != 0 ); + if (rhcoords) + { + X3DAUDIO_EMITTER lhEmitter; + memcpy(&lhEmitter, &emitter, sizeof(X3DAUDIO_EMITTER)); + lhEmitter.OrientFront.z = -emitter.OrientFront.z; + lhEmitter.OrientTop.z = -emitter.OrientTop.z; + lhEmitter.Position.z = -emitter.Position.z; + lhEmitter.Velocity.z = -emitter.Velocity.z; + + X3DAUDIO_LISTENER lhListener; + memcpy(&lhListener, &listener, sizeof(X3DAUDIO_LISTENER)); + lhListener.OrientFront.z = -listener.OrientFront.z; + lhListener.OrientTop.z = -listener.OrientTop.z; + lhListener.Position.z = -listener.Position.z; + lhListener.Velocity.z = -listener.Velocity.z; + + X3DAudioCalculate( engine->Get3DHandle(), &lhListener, &lhEmitter, dwCalcFlags, &mDSPSettings ); + } + else + { + X3DAudioCalculate( engine->Get3DHandle(), &listener, &emitter, dwCalcFlags, &mDSPSettings ); + } + + mDSPSettings.pMatrixCoefficients = nullptr; + + voice->SetFrequencyRatio( mFreqRatio * mDSPSettings.DopplerFactor ); + + auto direct = mDirectVoice; + assert( direct != 0 ); + voice->SetOutputMatrix( direct, mDSPSettings.SrcChannelCount, mDSPSettings.DstChannelCount, matrix ); + + if ( reverb ) + { + voice->SetOutputMatrix( reverb, 1, 1, &mDSPSettings.ReverbLevel ); + } + + if ( mFlags & SoundEffectInstance_ReverbUseFilters ) + { + XAUDIO2_FILTER_PARAMETERS filterDirect = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * mDSPSettings.LPFDirectCoefficient), 1.0f }; + // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here + voice->SetOutputFilterParameters( direct, &filterDirect ); + + if ( reverb ) + { + XAUDIO2_FILTER_PARAMETERS filterReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * mDSPSettings.LPFReverbCoefficient), 1.0f }; + // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here + voice->SetOutputFilterParameters( reverb, &filterReverb ); + } + } +} + + diff --git a/Kits/DirectXTK12/Audio/SoundCommon.h b/Kits/DirectXTK12/Audio/SoundCommon.h new file mode 100644 index 00000000..c8f3b7d1 --- /dev/null +++ b/Kits/DirectXTK12/Audio/SoundCommon.h @@ -0,0 +1,369 @@ +//-------------------------------------------------------------------------------------- +// File: SoundCommon.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "Audio.h" +#include "PlatformHelpers.h" + + +namespace DirectX +{ + // Helper for getting a format tag from a WAVEFORMATEX + inline uint32_t GetFormatTag( const WAVEFORMATEX* wfx ) + { + if ( wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) + { + if ( wfx->cbSize < ( sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) ) ) + return 0; + + static const GUID s_wfexBase = {0x00000000, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; + + auto wfex = reinterpret_cast( wfx ); + + if ( memcmp( reinterpret_cast(&wfex->SubFormat) + sizeof(DWORD), + reinterpret_cast(&s_wfexBase) + sizeof(DWORD), sizeof(GUID) - sizeof(DWORD) ) != 0 ) + { + return 0; + } + + return wfex->SubFormat.Data1; + } + else + { + return wfx->wFormatTag; + } + } + + + // Helper for validating wave format structure + bool IsValid( _In_ const WAVEFORMATEX* wfx ); + + + // Helper for getting a default channel mask from channels + uint32_t GetDefaultChannelMask( int channels ); + + + // Helpers for creating various wave format structures + void CreateIntegerPCM( _Out_ WAVEFORMATEX* wfx, int sampleRate, int channels, int sampleBits ); + void CreateFloatPCM( _Out_ WAVEFORMATEX* wfx, int sampleRate, int channels ); + void CreateADPCM( _Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int samplesPerBlock ); +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + void CreateXWMA( _Out_ WAVEFORMATEX* wfx, int sampleRate, int channels, int blockAlign, int avgBytes, bool wma3 ); +#endif +#if defined(_XBOX_ONE) && defined(_TITLE) + void CreateXMA2( _Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int bytesPerBlock, int blockCount, int samplesEncoded ); +#endif + + // Helper for computing pan volume matrix + bool ComputePan( float pan, int channels, _Out_writes_(16) float* matrix ); + + // Helper class for implementing SoundEffectInstance + class SoundEffectInstanceBase + { + public: + SoundEffectInstanceBase() : + voice( nullptr ), + state( STOPPED ), + engine( nullptr ), + mVolume( 1.f ), + mPitch( 0.f ), + mFreqRatio( 1.f ), + mPan( 0.f ), + mFlags( SoundEffectInstance_Default ), + mDirectVoice( nullptr ), + mReverbVoice( nullptr ) + { + } + + ~SoundEffectInstanceBase() + { + assert( !voice ); + } + + void Initialize( _In_ AudioEngine* eng, _In_ const WAVEFORMATEX* wfx, SOUND_EFFECT_INSTANCE_FLAGS flags ) + { + assert( eng != 0 ); + engine = eng; + mDirectVoice = eng->GetMasterVoice(); + mReverbVoice = eng->GetReverbVoice(); + + if ( eng->GetChannelMask() & SPEAKER_LOW_FREQUENCY ) + mFlags = flags | SoundEffectInstance_UseRedirectLFE; + else + mFlags = static_cast( static_cast(flags) & ~SoundEffectInstance_UseRedirectLFE ); + + memset( &mDSPSettings, 0, sizeof(X3DAUDIO_DSP_SETTINGS) ); + assert( wfx != 0 ); + mDSPSettings.SrcChannelCount = wfx->nChannels; + mDSPSettings.DstChannelCount = eng->GetOutputChannels(); + } + + void AllocateVoice( _In_ const WAVEFORMATEX* wfx ) + { + if ( voice ) + return; + + assert( engine != 0 ); + engine->AllocateVoice( wfx, mFlags, false, &voice ); + } + + void DestroyVoice() + { + if ( voice ) + { + assert( engine != 0 ); + engine->DestroyVoice( voice ); + voice = nullptr; + } + } + + bool Play() // Returns true if STOPPED -> PLAYING + { + if ( voice ) + { + if ( state == PAUSED ) + { + HRESULT hr = voice->Start( 0 ); + ThrowIfFailed( hr ); + state = PLAYING; + } + else if ( state != PLAYING ) + { + if ( mVolume != 1.f ) + { + HRESULT hr = voice->SetVolume( mVolume ); + ThrowIfFailed( hr ); + } + + if ( mPitch != 0.f ) + { + mFreqRatio = XAudio2SemitonesToFrequencyRatio( mPitch * 12.f ); + + HRESULT hr = voice->SetFrequencyRatio( mFreqRatio ); + ThrowIfFailed( hr ); + } + + if ( mPan != 0.f ) + { + SetPan( mPan ); + } + + HRESULT hr = voice->Start( 0 ); + ThrowIfFailed( hr ); + state = PLAYING; + return true; + } + } + return false; + } + + void Stop( bool immediate, bool& looped ) + { + if ( !voice ) + { + state = STOPPED; + return; + } + + if ( immediate ) + { + state = STOPPED; + voice->Stop( 0 ); + voice->FlushSourceBuffers(); + } + else if ( looped ) + { + looped = false; + voice->ExitLoop(); + } + else + { + voice->Stop( XAUDIO2_PLAY_TAILS ); + } + } + + void Pause() + { + if ( voice && state == PLAYING ) + { + state = PAUSED; + + voice->Stop( 0 ); + } + } + + void Resume() + { + if ( voice && state == PAUSED ) + { + HRESULT hr = voice->Start( 0 ); + ThrowIfFailed( hr ); + state = PLAYING; + } + } + + void SetVolume( float volume ) + { + assert( volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL ); + + mVolume = volume; + + if ( voice ) + { + HRESULT hr = voice->SetVolume( volume ); + ThrowIfFailed( hr ); + } + } + + void SetPitch( float pitch ) + { + assert( pitch >= -1.f && pitch <= 1.f ); + + if ( ( mFlags & SoundEffectInstance_NoSetPitch ) && pitch != 0.f ) + { + DebugTrace( "ERROR: Sound effect instance was created with the NoSetPitch flag\n" ); + throw std::exception( "SetPitch" ); + } + + mPitch = pitch; + + if ( voice ) + { + mFreqRatio = XAudio2SemitonesToFrequencyRatio( mPitch * 12.f ); + + HRESULT hr = voice->SetFrequencyRatio( mFreqRatio ); + ThrowIfFailed( hr ); + } + } + + void SetPan( float pan ); + + void Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords ); + + SoundState GetState( bool autostop ) + { + if ( autostop && voice && ( state == PLAYING ) ) + { + XAUDIO2_VOICE_STATE xstate; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + voice->GetState( &xstate, XAUDIO2_VOICE_NOSAMPLESPLAYED ); +#else + voice->GetState( &xstate ); +#endif + + if ( !xstate.BuffersQueued ) + { + // Automatic stop if the buffer has finished playing + voice->Stop(); + state = STOPPED; + } + } + + return state; + } + + int GetPendingBufferCount() const + { + if ( !voice ) + return 0; + + XAUDIO2_VOICE_STATE xstate; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + voice->GetState( &xstate, XAUDIO2_VOICE_NOSAMPLESPLAYED ); +#else + voice->GetState( &xstate ); +#endif + return static_cast( xstate.BuffersQueued ); + } + + void OnCriticalError() + { + if ( voice ) + { + voice->DestroyVoice(); + voice = nullptr; + } + state = STOPPED; + mDirectVoice = nullptr; + mReverbVoice = nullptr; + } + + void OnReset() + { + assert( engine != 0 ); + mDirectVoice = engine->GetMasterVoice(); + mReverbVoice = engine->GetReverbVoice(); + + if ( engine->GetChannelMask() & SPEAKER_LOW_FREQUENCY ) + mFlags = mFlags | SoundEffectInstance_UseRedirectLFE; + else + mFlags = static_cast( static_cast(mFlags) & ~SoundEffectInstance_UseRedirectLFE ); + + mDSPSettings.DstChannelCount = engine->GetOutputChannels(); + } + + void OnDestroy() + { + if ( voice ) + { + voice->Stop( 0 ); + voice->FlushSourceBuffers(); + voice->DestroyVoice(); + voice = nullptr; + } + state = STOPPED; + engine = nullptr; + mDirectVoice = nullptr; + mReverbVoice = nullptr; + } + + void OnTrim() + { + if ( voice && ( state == STOPPED ) ) + { + engine->DestroyVoice( voice ); + voice = nullptr; + } + } + + void GatherStatistics( AudioStatistics& stats ) const + { + ++stats.allocatedInstances; + if ( voice ) + { + ++stats.allocatedVoices; + + if ( mFlags & SoundEffectInstance_Use3D ) + ++stats.allocatedVoices3d; + + if ( state == PLAYING ) + ++stats.playingInstances; + } + } + + IXAudio2SourceVoice* voice; + SoundState state; + AudioEngine* engine; + + private: + float mVolume; + float mPitch; + float mFreqRatio; + float mPan; + SOUND_EFFECT_INSTANCE_FLAGS mFlags; + IXAudio2Voice* mDirectVoice; + IXAudio2Voice* mReverbVoice; + X3DAUDIO_DSP_SETTINGS mDSPSettings; + }; +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Audio/SoundEffect.cpp b/Kits/DirectXTK12/Audio/SoundEffect.cpp new file mode 100644 index 00000000..7cfdb8ce --- /dev/null +++ b/Kits/DirectXTK12/Audio/SoundEffect.cpp @@ -0,0 +1,617 @@ +//-------------------------------------------------------------------------------------- +// File: SoundEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "WAVFileReader.h" +#include "SoundCommon.h" + +#include + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#endif + +using namespace DirectX; + + +//====================================================================================== +// SoundEffect +//====================================================================================== + +// Internal object implementation class. +class SoundEffect::Impl : public IVoiceNotify +{ +public: + explicit Impl( _In_ AudioEngine* engine ) : + mWaveFormat( nullptr ), + mStartAudio( nullptr ), + mAudioBytes( 0 ), + mLoopStart( 0 ), + mLoopLength( 0 ), + mEngine( engine ), + mOneShots( 0 ) +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + , mSeekCount( 0 ) + , mSeekTable( nullptr ) +#endif +#if defined(_XBOX_ONE) && defined(_TITLE) + , mXMAMemory( nullptr ) +#endif + { + assert( mEngine != 0 ); + mEngine->RegisterNotify( this, false ); + } + + virtual ~Impl() + { + if ( !mInstances.empty() ) + { + DebugTrace( "WARNING: Destroying SoundEffect with %Iu outstanding SoundEffectInstances\n", mInstances.size() ); + + for( auto it = mInstances.begin(); it != mInstances.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnDestroyParent(); + } + + mInstances.clear(); + } + + if ( mOneShots > 0 ) + { + DebugTrace( "WARNING: Destroying SoundEffect with %u outstanding one shot effects\n", mOneShots ); + } + + if ( mEngine ) + { + mEngine->UnregisterNotify( this, true, false ); + mEngine = nullptr; + } + +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( mXMAMemory ) + { + ApuFree( mXMAMemory ); + mXMAMemory = nullptr; + } +#endif + } + + HRESULT Initialize( _In_ AudioEngine* engine, _Inout_ std::unique_ptr& wavData, + _In_ const WAVEFORMATEX* wfx, _In_reads_bytes_(audioBytes) const uint8_t* startAudio, size_t audioBytes, +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + _In_reads_opt_(seekCount) const uint32_t* seekTable, size_t seekCount, +#endif + uint32_t loopStart, uint32_t loopLength ); + + void Play( float volume, float pitch, float pan ); + + // IVoiceNotify + virtual void __cdecl OnBufferEnd() override + { + InterlockedDecrement( &mOneShots ); + } + + virtual void __cdecl OnCriticalError() override + { + mOneShots = 0; + } + + virtual void __cdecl OnReset() override + { + // No action required + } + + virtual void __cdecl OnUpdate() override + { + // We do not register for update notification + assert(false); + } + + virtual void __cdecl OnDestroyEngine() override + { + mEngine = nullptr; + mOneShots = 0; + } + + virtual void __cdecl OnTrim() override + { + // No action required + } + + virtual void __cdecl GatherStatistics( AudioStatistics& stats ) const override + { + stats.playingOneShots += mOneShots; + stats.audioBytes += mAudioBytes; + +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( mXMAMemory ) + stats.xmaAudioBytes += mAudioBytes; +#endif + } + + const WAVEFORMATEX* mWaveFormat; + const uint8_t* mStartAudio; + uint32_t mAudioBytes; + uint32_t mLoopStart; + uint32_t mLoopLength; + AudioEngine* mEngine; + std::list mInstances; + uint32_t mOneShots; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + uint32_t mSeekCount; + const uint32_t* mSeekTable; +#endif + +private: + std::unique_ptr mWavData; + +#if defined(_XBOX_ONE) && defined(_TITLE) + void* mXMAMemory; +#endif +}; + + +_Use_decl_annotations_ +HRESULT SoundEffect::Impl::Initialize( AudioEngine* engine, std::unique_ptr& wavData, + const WAVEFORMATEX* wfx, const uint8_t* startAudio, size_t audioBytes, +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + const uint32_t* seekTable, size_t seekCount, +#endif + uint32_t loopStart, uint32_t loopLength ) +{ + if ( !engine || !IsValid( wfx ) || !startAudio || !audioBytes || !wavData ) + return E_INVALIDARG; + +#ifdef _M_X64 + if ( audioBytes > 0xFFFFFFFF ) + return E_INVALIDARG; +#endif + + switch( GetFormatTag( wfx ) ) + { + case WAVE_FORMAT_PCM: + case WAVE_FORMAT_IEEE_FLOAT: + case WAVE_FORMAT_ADPCM: + // Take ownership of the buffer + mWavData.reset( wavData.release() ); + + // WARNING: We assume the wfx and startAudio parameters are pointers into the wavData memory buffer + mWaveFormat = wfx; + mStartAudio = startAudio; + break; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + if ( !seekCount || !seekTable ) + { + DebugTrace( "ERROR: SoundEffect format xWMA requires seek table\n" ); + return E_FAIL; + } + +#ifdef _M_X64 + if ( seekCount > 0xFFFFFFFF ) + return E_INVALIDARG; +#endif + + // Take ownership of the buffer + mWavData.reset( wavData.release() ); + + // WARNING: We assume the wfx, startAudio, and mSeekTable parameters are pointers into the wavData memory buffer + mWaveFormat = wfx; + mStartAudio = startAudio; + mSeekCount = static_cast( seekCount ); + mSeekTable = seekTable; + break; + +#endif // _XBOX_ONE || _WIN32_WINNT < _WIN32_WINNT_WIN8 || _WIN32_WINNT >= _WIN32_WINNT_WIN10 + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case WAVE_FORMAT_XMA2: + if ( !seekCount || !seekTable ) + { + DebugTrace( "ERROR: SoundEffect format XMA2 requires seek table\n" ); + return E_FAIL; + } + +#ifdef _M_X64 + if ( seekCount > 0xFFFFFFFF ) + return E_INVALIDARG; +#endif + + { + HRESULT hr = ApuAlloc( &mXMAMemory, nullptr, + static_cast( audioBytes ), SHAPE_XMA_INPUT_BUFFER_ALIGNMENT ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: ApuAlloc failed. Did you allocate a large enough heap with ApuCreateHeap for all your XMA wave data?\n" ); + return hr; + } + } + + memcpy( mXMAMemory, startAudio, audioBytes ); + mStartAudio = reinterpret_cast( mXMAMemory ); + + mWavData.reset( new uint8_t[ sizeof(XMA2WAVEFORMATEX) + ( seekCount * sizeof(uint32_t) ) ] ); + + memcpy( mWavData.get(), wfx, sizeof(XMA2WAVEFORMATEX) ); + mWaveFormat = reinterpret_cast( mWavData.get() ); + + // XMA seek table is Big-Endian + { + auto dest = reinterpret_cast( mWavData.get() + sizeof(XMA2WAVEFORMATEX) ); + for( size_t k = 0; k < seekCount; ++k ) + { + dest[ k ] = _byteswap_ulong( seekTable[ k ]) ; + } + } + + mSeekCount = static_cast( seekCount ); + mSeekTable = reinterpret_cast( mWavData.get() + sizeof(XMA2WAVEFORMATEX) ); + + wavData.reset(); + break; + +#endif // _XBOX_ONE && _TITLE + + default: + { + DebugTrace( "ERROR: SoundEffect encountered an unsupported format tag (%u)\n", wfx->wFormatTag ); + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + } + + mAudioBytes = static_cast( audioBytes ); + mLoopStart = loopStart; + mLoopLength = loopLength; + + return S_OK; +} + + +void SoundEffect::Impl::Play( float volume, float pitch, float pan ) +{ + assert( volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL ); + assert( pitch >= -1.f && pitch <= 1.f ); + assert( pan >= -1.f && pan <= 1.f ); + + IXAudio2SourceVoice* voice = nullptr; + mEngine->AllocateVoice( mWaveFormat, SoundEffectInstance_Default, true, &voice ); + + if ( !voice ) + return; + + if ( volume != 1.f ) + { + HRESULT hr = voice->SetVolume( volume ); + ThrowIfFailed( hr ); + } + + if ( pitch != 0.f ) + { + float fr = XAudio2SemitonesToFrequencyRatio( pitch * 12.f ); + + HRESULT hr = voice->SetFrequencyRatio( fr ); + ThrowIfFailed( hr ); + } + + if ( pan != 0.f ) + { + float matrix[16]; + if (ComputePan(pan, mWaveFormat->nChannels, matrix)) + { + HRESULT hr = voice->SetOutputMatrix(nullptr, mWaveFormat->nChannels, mEngine->GetOutputChannels(), matrix); + ThrowIfFailed( hr ); + } + } + + HRESULT hr = voice->Start( 0 ); + ThrowIfFailed( hr ); + + XAUDIO2_BUFFER buffer = {}; + buffer.AudioBytes = mAudioBytes; + buffer.pAudioData = mStartAudio; + buffer.Flags = XAUDIO2_END_OF_STREAM; + buffer.pContext = this; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + uint32_t tag = GetFormatTag( mWaveFormat ); + if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 ) + { + XAUDIO2_BUFFER_WMA wmaBuffer = {}; + wmaBuffer.PacketCount = mSeekCount; + wmaBuffer.pDecodedPacketCumulativeBytes = mSeekTable; + + hr = voice->SubmitSourceBuffer( &buffer, &wmaBuffer ); + } + else +#endif + { + hr = voice->SubmitSourceBuffer( &buffer, nullptr ); + } + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) when submitting buffer:\n", hr ); + DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %u bytes\n", mWaveFormat->wFormatTag, + mWaveFormat->nChannels, mWaveFormat->wBitsPerSample, mWaveFormat->nSamplesPerSec, mAudioBytes ); + throw std::exception( "SubmitSourceBuffer" ); + } + + InterlockedIncrement( &mOneShots ); +} + + +//-------------------------------------------------------------------------------------- +// SoundEffect +//-------------------------------------------------------------------------------------- + +// Public constructors. +_Use_decl_annotations_ +SoundEffect::SoundEffect( AudioEngine* engine, const wchar_t* waveFileName ) + : pImpl(new Impl(engine) ) +{ + WAVData wavInfo; + std::unique_ptr wavData; + HRESULT hr = LoadWAVAudioFromFileEx( waveFileName, wavData, wavInfo ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) to load from .wav file \"%ls\"\n", hr, waveFileName ); + throw std::exception( "SoundEffect" ); + } + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + hr = pImpl->Initialize( engine, wavData, wavInfo.wfx, wavInfo.startAudio, wavInfo.audioBytes, + wavInfo.seek, wavInfo.seekCount, + wavInfo.loopStart, wavInfo.loopLength ); +#else + hr = pImpl->Initialize( engine, wavData, wavInfo.wfx, wavInfo.startAudio, wavInfo.audioBytes, + wavInfo.loopStart, wavInfo.loopLength ); +#endif + + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) to intialize from .wav file \"%ls\"\n", hr, waveFileName ); + throw std::exception( "SoundEffect" ); + } +} + + +_Use_decl_annotations_ +SoundEffect::SoundEffect( AudioEngine* engine, std::unique_ptr& wavData, + const WAVEFORMATEX* wfx, const uint8_t* startAudio, size_t audioBytes ) + : pImpl(new Impl(engine) ) +{ +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + HRESULT hr = pImpl->Initialize( engine, wavData, wfx, startAudio, audioBytes, nullptr, 0, 0, 0 ); +#else + HRESULT hr = pImpl->Initialize( engine, wavData, wfx, startAudio, audioBytes, 0, 0 ); +#endif + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) to intialize\n", hr ); + throw std::exception( "SoundEffect" ); + } +} + + +_Use_decl_annotations_ +SoundEffect::SoundEffect( AudioEngine* engine, std::unique_ptr& wavData, + const WAVEFORMATEX* wfx, const uint8_t* startAudio, size_t audioBytes, + uint32_t loopStart, uint32_t loopLength ) + : pImpl(new Impl(engine) ) +{ +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + HRESULT hr = pImpl->Initialize( engine, wavData, wfx, startAudio, audioBytes, nullptr, 0, loopStart, loopLength ); +#else + HRESULT hr = pImpl->Initialize( engine, wavData, wfx, startAudio, audioBytes, loopStart, loopLength ); +#endif + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) to intialize\n", hr ); + throw std::exception( "SoundEffect" ); + } +} + + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +_Use_decl_annotations_ +SoundEffect::SoundEffect( AudioEngine* engine, std::unique_ptr& wavData, + const WAVEFORMATEX* wfx, const uint8_t* startAudio, size_t audioBytes, + const uint32_t* seekTable, size_t seekCount ) +{ + HRESULT hr = pImpl->Initialize( engine, wavData, wfx, startAudio, audioBytes, seekTable, seekCount, 0, 0 ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: SoundEffect failed (%08X) to intialize\n", hr ); + throw std::exception( "SoundEffect" ); + } +} + +#endif + + +// Move constructor. +SoundEffect::SoundEffect(SoundEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +SoundEffect& SoundEffect::operator= (SoundEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +SoundEffect::~SoundEffect() +{ +} + + +// Public methods. +void SoundEffect::Play() +{ + pImpl->Play( 1.f, 0.f, 0.f ); +} + + +void SoundEffect::Play( float volume, float pitch, float pan ) +{ + pImpl->Play( volume, pitch, pan ); +} + + +std::unique_ptr SoundEffect::CreateInstance( SOUND_EFFECT_INSTANCE_FLAGS flags ) +{ + auto effect = new SoundEffectInstance( pImpl->mEngine, this, flags ); + assert( effect != 0 ); + pImpl->mInstances.emplace_back( effect ); + return std::unique_ptr( effect ); +} + + +void SoundEffect::UnregisterInstance( _In_ SoundEffectInstance* instance ) +{ + auto it = std::find( pImpl->mInstances.begin(), pImpl->mInstances.end(), instance ); + if ( it == pImpl->mInstances.end() ) + return; + + pImpl->mInstances.erase( it ); +} + + +// Public accessors. +bool SoundEffect::IsInUse() const +{ + return ( pImpl->mOneShots > 0 ) || !pImpl->mInstances.empty(); +} + + +size_t SoundEffect::GetSampleSizeInBytes() const +{ + return pImpl->mAudioBytes; +} + + +size_t SoundEffect::GetSampleDuration() const +{ + if ( !pImpl->mWaveFormat || !pImpl->mWaveFormat->nChannels ) + return 0; + + switch( GetFormatTag( pImpl->mWaveFormat ) ) + { + case WAVE_FORMAT_ADPCM: + { + auto adpcmFmt = reinterpret_cast( pImpl->mWaveFormat ); + + uint64_t duration = uint64_t( pImpl->mAudioBytes / adpcmFmt->wfx.nBlockAlign ) * adpcmFmt->wSamplesPerBlock; + int partial = pImpl->mAudioBytes % adpcmFmt->wfx.nBlockAlign; + if ( partial ) + { + if ( partial >= ( 7 * adpcmFmt->wfx.nChannels ) ) + duration += ( partial * 2 / adpcmFmt->wfx.nChannels - 12 ); + } + return static_cast( duration ); + } + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + if ( pImpl->mSeekTable && pImpl->mSeekCount > 0 ) + { + return pImpl->mSeekTable[ pImpl->mSeekCount - 1 ] / uint32_t( 2 * pImpl->mWaveFormat->nChannels ); + } + break; + +#endif + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case WAVE_FORMAT_XMA2: + return reinterpret_cast( pImpl->mWaveFormat )->SamplesEncoded; + +#endif + + default: + if ( pImpl->mWaveFormat->wBitsPerSample > 0 ) + { + return static_cast( ( uint64_t( pImpl->mAudioBytes ) * 8 ) + / uint64_t( pImpl->mWaveFormat->wBitsPerSample * pImpl->mWaveFormat->nChannels ) ); + } + } + + return 0; +} + + +size_t SoundEffect::GetSampleDurationMS() const +{ + if ( !pImpl->mWaveFormat || !pImpl->mWaveFormat->nSamplesPerSec ) + return 0; + + uint64_t samples = GetSampleDuration(); + return static_cast( ( samples * 1000 ) / pImpl->mWaveFormat->nSamplesPerSec ); +} + + +const WAVEFORMATEX* SoundEffect::GetFormat() const +{ + return pImpl->mWaveFormat; +} + + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +bool SoundEffect::FillSubmitBuffer( _Out_ XAUDIO2_BUFFER& buffer, _Out_ XAUDIO2_BUFFER_WMA& wmaBuffer ) const +{ + memset( &buffer, 0, sizeof(buffer) ); + memset( &wmaBuffer, 0, sizeof(wmaBuffer) ); + + buffer.AudioBytes = pImpl->mAudioBytes; + buffer.pAudioData = pImpl->mStartAudio; + buffer.LoopBegin = pImpl->mLoopStart; + buffer.LoopLength = pImpl->mLoopLength; + + uint32_t tag = GetFormatTag( pImpl->mWaveFormat ); + if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 ) + { + wmaBuffer.PacketCount = pImpl->mSeekCount; + wmaBuffer.pDecodedPacketCumulativeBytes = pImpl->mSeekTable; + return true; + } + + return false; +} + +#else + +void SoundEffect::FillSubmitBuffer( _Out_ XAUDIO2_BUFFER& buffer ) const +{ + memset( &buffer, 0, sizeof(buffer) ); + buffer.AudioBytes = pImpl->mAudioBytes; + buffer.pAudioData = pImpl->mStartAudio; + buffer.LoopBegin = pImpl->mLoopStart; + buffer.LoopLength = pImpl->mLoopLength; +} + +#endif diff --git a/Kits/DirectXTK12/Audio/SoundEffectInstance.cpp b/Kits/DirectXTK12/Audio/SoundEffectInstance.cpp new file mode 100644 index 00000000..d1add351 --- /dev/null +++ b/Kits/DirectXTK12/Audio/SoundEffectInstance.cpp @@ -0,0 +1,334 @@ +//-------------------------------------------------------------------------------------- +// File: SoundEffectInstance.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SoundCommon.h" + +using namespace DirectX; + + +//====================================================================================== +// SoundEffectInstance +//====================================================================================== + +// Internal object implementation class. +class SoundEffectInstance::Impl : public IVoiceNotify +{ +public: + Impl( _In_ AudioEngine* engine, _In_ SoundEffect* effect, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + mBase(), + mEffect( effect ), + mWaveBank( nullptr ), + mIndex( 0 ), + mLooped( false ) + { + assert( engine != 0 ); + engine->RegisterNotify( this, false ); + + assert( mEffect != 0 ); + mBase.Initialize( engine, effect->GetFormat(), flags ); + } + + Impl( _In_ AudioEngine* engine, _In_ WaveBank* waveBank, uint32_t index, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + mBase(), + mEffect( nullptr ), + mWaveBank( waveBank ), + mIndex( index ), + mLooped( false ) + { + assert( engine != 0 ); + engine->RegisterNotify( this, false ); + + char buff[64]; + auto wfx = reinterpret_cast( buff ); + assert( mWaveBank != 0 ); + mBase.Initialize( engine, mWaveBank->GetFormat( index, wfx, 64 ), flags ); + } + + virtual ~Impl() + { + mBase.DestroyVoice(); + + if ( mBase.engine ) + { + mBase.engine->UnregisterNotify( this, false, false ); + mBase.engine = nullptr; + } + } + + void Play( bool loop ); + + // IVoiceNotify + virtual void __cdecl OnBufferEnd() override + { + // We don't register for this notification for SoundEffectInstances, so this should not be invoked + assert( false ); + } + + virtual void __cdecl OnCriticalError() override + { + mBase.OnCriticalError(); + } + + virtual void __cdecl OnReset() override + { + mBase.OnReset(); + } + + virtual void __cdecl OnUpdate() override + { + // We do not register for update notification + assert(false); + } + + virtual void __cdecl OnDestroyEngine() override + { + mBase.OnDestroy(); + } + + virtual void __cdecl OnTrim() override + { + mBase.OnTrim(); + } + + virtual void __cdecl GatherStatistics( AudioStatistics& stats ) const override + { + mBase.GatherStatistics(stats); + } + + SoundEffectInstanceBase mBase; + SoundEffect* mEffect; + WaveBank* mWaveBank; + uint32_t mIndex; + bool mLooped; +}; + + +void SoundEffectInstance::Impl::Play( bool loop ) +{ + if ( !mBase.voice ) + { + if ( mWaveBank ) + { + char buff[64]; + auto wfx = reinterpret_cast( buff ); + mBase.AllocateVoice( mWaveBank->GetFormat( mIndex, wfx, 64) ); + } + else + { + assert( mEffect != 0 ); + mBase.AllocateVoice( mEffect->GetFormat() ); + } + } + + if ( !mBase.Play() ) + return; + + // Submit audio data for STOPPED -> PLAYING state transition + XAUDIO2_BUFFER buffer; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + bool iswma = false; + XAUDIO2_BUFFER_WMA wmaBuffer; + if ( mWaveBank ) + { + iswma = mWaveBank->FillSubmitBuffer( mIndex, buffer, wmaBuffer ); + } + else + { + assert( mEffect != 0 ); + iswma = mEffect->FillSubmitBuffer( buffer, wmaBuffer ); + } + +#else + + if ( mWaveBank ) + { + mWaveBank->FillSubmitBuffer( mIndex, buffer ); + } + else + { + assert( mEffect != 0 ); + mEffect->FillSubmitBuffer( buffer ); + } + +#endif + + buffer.Flags = XAUDIO2_END_OF_STREAM; + if ( loop ) + { + mLooped = true; + buffer.LoopCount = XAUDIO2_LOOP_INFINITE; + } + else + { + mLooped = false; + buffer.LoopCount = buffer.LoopBegin = buffer.LoopLength = 0; + } + buffer.pContext = nullptr; + + HRESULT hr; +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + if ( iswma ) + { + hr = mBase.voice->SubmitSourceBuffer( &buffer, &wmaBuffer ); + } + else +#endif + { + hr = mBase.voice->SubmitSourceBuffer( &buffer, nullptr ); + } + + if ( FAILED(hr) ) + { +#ifdef _DEBUG + DebugTrace( "ERROR: SoundEffectInstance failed (%08X) when submitting buffer:\n", hr ); + + char buff[64]; + auto wfx = ( mWaveBank ) ? mWaveBank->GetFormat( mIndex, reinterpret_cast( buff ), 64 ) + : mEffect->GetFormat(); + + size_t length = ( mWaveBank ) ? mWaveBank->GetSampleSizeInBytes( mIndex ) : mEffect->GetSampleSizeInBytes(); + + DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %Iu bytes\n", wfx->wFormatTag, + wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec, length ); +#endif + mBase.Stop( true, mLooped ); + throw std::exception( "SubmitSourceBuffer" ); + } +} + + +//-------------------------------------------------------------------------------------- +// SoundEffectInstance +//-------------------------------------------------------------------------------------- + +// Private constructors +_Use_decl_annotations_ +SoundEffectInstance::SoundEffectInstance( AudioEngine* engine, SoundEffect* effect, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + pImpl( new Impl( engine, effect, flags ) ) +{ +} + +_Use_decl_annotations_ +SoundEffectInstance::SoundEffectInstance( AudioEngine* engine, WaveBank* waveBank, int index, SOUND_EFFECT_INSTANCE_FLAGS flags ) : + pImpl( new Impl( engine, waveBank, index, flags ) ) +{ +} + + +// Move constructor. +SoundEffectInstance::SoundEffectInstance(SoundEffectInstance&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +SoundEffectInstance& SoundEffectInstance::operator= (SoundEffectInstance&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +SoundEffectInstance::~SoundEffectInstance() +{ + if( pImpl ) + { + if ( pImpl->mWaveBank ) + { + pImpl->mWaveBank->UnregisterInstance( this ); + pImpl->mWaveBank = nullptr; + } + + if ( pImpl->mEffect ) + { + pImpl->mEffect->UnregisterInstance( this ); + pImpl->mEffect = nullptr; + } + } +} + + +// Public methods. +void SoundEffectInstance::Play( bool loop ) +{ + pImpl->Play( loop ); +} + + +void SoundEffectInstance::Stop( bool immediate ) +{ + pImpl->mBase.Stop( immediate, pImpl->mLooped ); +} + + +void SoundEffectInstance::Pause() +{ + pImpl->mBase.Pause(); +} + + +void SoundEffectInstance::Resume() +{ + pImpl->mBase.Resume(); +} + + +void SoundEffectInstance::SetVolume( float volume ) +{ + pImpl->mBase.SetVolume( volume ); +} + + +void SoundEffectInstance::SetPitch( float pitch ) +{ + pImpl->mBase.SetPitch( pitch ); +} + + +void SoundEffectInstance::SetPan( float pan ) +{ + pImpl->mBase.SetPan( pan ); +} + + +void SoundEffectInstance::Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords ) +{ + pImpl->mBase.Apply3D( listener, emitter, rhcoords ); +} + + +// Public accessors. +bool SoundEffectInstance::IsLooped() const +{ + return pImpl->mLooped; +} + + +SoundState SoundEffectInstance::GetState() +{ + return pImpl->mBase.GetState( true ); +} + + +// Notifications. +void SoundEffectInstance::OnDestroyParent() +{ + pImpl->mBase.OnDestroy(); + pImpl->mWaveBank = nullptr; + pImpl->mEffect = nullptr; +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Audio/WAVFileReader.cpp b/Kits/DirectXTK12/Audio/WAVFileReader.cpp new file mode 100644 index 00000000..4ecff8e2 --- /dev/null +++ b/Kits/DirectXTK12/Audio/WAVFileReader.cpp @@ -0,0 +1,681 @@ +//-------------------------------------------------------------------------------------- +// File: WAVFileReader.cpp +// +// Functions for loading WAV audio files +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#include "pch.h" +#include "PlatformHelpers.h" +#include "WAVFileReader.h" + +using namespace DirectX; + + +namespace +{ + +//-------------------------------------------------------------------------------------- +// .WAV files +//-------------------------------------------------------------------------------------- +const uint32_t FOURCC_RIFF_TAG = 'FFIR'; +const uint32_t FOURCC_FORMAT_TAG = ' tmf'; +const uint32_t FOURCC_DATA_TAG = 'atad'; +const uint32_t FOURCC_WAVE_FILE_TAG = 'EVAW'; +const uint32_t FOURCC_XWMA_FILE_TAG = 'AMWX'; +const uint32_t FOURCC_DLS_SAMPLE = 'pmsw'; +const uint32_t FOURCC_MIDI_SAMPLE = 'lpms'; +const uint32_t FOURCC_XWMA_DPDS = 'sdpd'; +const uint32_t FOURCC_XMA_SEEK = 'kees'; + +#pragma pack(push,1) +struct RIFFChunk +{ + uint32_t tag; + uint32_t size; +}; + +struct RIFFChunkHeader +{ + uint32_t tag; + uint32_t size; + uint32_t riff; +}; + +struct DLSLoop +{ + static const uint32_t LOOP_TYPE_FORWARD = 0x00000000; + static const uint32_t LOOP_TYPE_RELEASE = 0x00000001; + + uint32_t size; + uint32_t loopType; + uint32_t loopStart; + uint32_t loopLength; +}; + +struct RIFFDLSSample +{ + static const uint32_t OPTIONS_NOTRUNCATION = 0x00000001; + static const uint32_t OPTIONS_NOCOMPRESSION = 0x00000002; + + uint32_t size; + uint16_t unityNote; + int16_t fineTune; + int32_t gain; + uint32_t options; + uint32_t loopCount; +}; + +struct MIDILoop +{ + static const uint32_t LOOP_TYPE_FORWARD = 0x00000000; + static const uint32_t LOOP_TYPE_ALTERNATING = 0x00000001; + static const uint32_t LOOP_TYPE_BACKWARD = 0x00000002; + + uint32_t cuePointId; + uint32_t type; + uint32_t start; + uint32_t end; + uint32_t fraction; + uint32_t playCount; +}; + +struct RIFFMIDISample +{ + uint32_t manufacturerId; + uint32_t productId; + uint32_t samplePeriod; + uint32_t unityNode; + uint32_t pitchFraction; + uint32_t SMPTEFormat; + uint32_t SMPTEOffset; + uint32_t loopCount; + uint32_t samplerData; +}; +#pragma pack(pop) + +static_assert( sizeof(RIFFChunk) == 8, "structure size mismatch"); +static_assert( sizeof(RIFFChunkHeader) == 12, "structure size mismatch"); +static_assert( sizeof(DLSLoop) == 16, "structure size mismatch"); +static_assert( sizeof(RIFFDLSSample) == 20, "structure size mismatch"); +static_assert( sizeof(MIDILoop) == 24, "structure size mismatch"); +static_assert( sizeof(RIFFMIDISample) == 36, "structure size mismatch"); + +}; + + +//-------------------------------------------------------------------------------------- +static const RIFFChunk* FindChunk( _In_reads_bytes_(sizeBytes) const uint8_t* data, _In_ size_t sizeBytes, _In_ uint32_t tag ) +{ + if ( !data ) + return nullptr; + + const uint8_t* ptr = data; + const uint8_t* end = data + sizeBytes; + + while ( end > ( ptr + sizeof(RIFFChunk) ) ) + { + auto header = reinterpret_cast( ptr ); + if ( header->tag == tag ) + return header; + + ptrdiff_t offset = header->size + sizeof(RIFFChunk); + ptr += offset; + } + + return nullptr; +} + + +//-------------------------------------------------------------------------------------- +static HRESULT WaveFindFormatAndData( _In_reads_bytes_(wavDataSize) const uint8_t* wavData, _In_ size_t wavDataSize, + _Outptr_ const WAVEFORMATEX** pwfx, _Outptr_ const uint8_t** pdata, _Out_ uint32_t* dataSize, + _Out_ bool& dpds, _Out_ bool& seek ) +{ + if ( !wavData || !pwfx ) + return E_POINTER; + + dpds = seek = false; + + if (wavDataSize < (sizeof(RIFFChunk)*2 + sizeof(uint32_t) + sizeof(WAVEFORMAT) ) ) + { + return E_FAIL; + } + + const uint8_t* wavEnd = wavData + wavDataSize; + + // Locate RIFF 'WAVE' + auto riffChunk = FindChunk( wavData, wavDataSize, FOURCC_RIFF_TAG ); + if ( !riffChunk || riffChunk->size < 4 ) + { + return E_FAIL; + } + + auto riffHeader = reinterpret_cast( riffChunk ); + if ( riffHeader->riff != FOURCC_WAVE_FILE_TAG && riffHeader->riff != FOURCC_XWMA_FILE_TAG ) + { + return E_FAIL; + } + + // Locate 'fmt ' + auto ptr = reinterpret_cast( riffHeader ) + sizeof(RIFFChunkHeader); + if ( ( ptr + sizeof(RIFFChunk) ) > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + auto fmtChunk = FindChunk( ptr, riffHeader->size, FOURCC_FORMAT_TAG ); + if ( !fmtChunk || fmtChunk->size < sizeof(PCMWAVEFORMAT) ) + { + return E_FAIL; + } + + ptr = reinterpret_cast( fmtChunk ) + sizeof( RIFFChunk ); + if ( ptr + fmtChunk->size > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + auto wf = reinterpret_cast( ptr ); + + // Validate WAVEFORMAT (focused on chunk size and format tag, not other data that XAUDIO2 will validate) + switch( wf->wFormatTag ) + { + case WAVE_FORMAT_PCM: + case WAVE_FORMAT_IEEE_FLOAT: + // Can be a PCMWAVEFORMAT (8 bytes) or WAVEFORMATEX (10 bytes) + // We validiated chunk as at least sizeof(PCMWAVEFORMAT) above + break; + + default: + { + if ( fmtChunk->size < sizeof(WAVEFORMATEX) ) + { + return E_FAIL; + } + + auto wfx = reinterpret_cast( ptr ); + + if ( fmtChunk->size < ( sizeof(WAVEFORMATEX) + wfx->cbSize ) ) + { + return E_FAIL; + } + + switch( wfx->wFormatTag ) + { + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + dpds = true; + break; + + case 0x166 /*WAVE_FORMAT_XMA2*/: // XMA2 is supported by Xbox One + if ( ( fmtChunk->size < 52 /*sizeof(XMA2WAVEFORMATEX)*/ ) || ( wfx->cbSize < 34 /*( sizeof(XMA2WAVEFORMATEX) - sizeof(WAVEFORMATEX) )*/ ) ) + { + return E_FAIL; + } + seek = true; + break; + + case WAVE_FORMAT_ADPCM: + if ( ( fmtChunk->size < ( sizeof(WAVEFORMATEX) + 32 ) ) || ( wfx->cbSize < 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/ ) ) + { + return E_FAIL; + } + break; + + case WAVE_FORMAT_EXTENSIBLE: + if ( ( fmtChunk->size < sizeof(WAVEFORMATEXTENSIBLE) ) || ( wfx->cbSize < ( sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) ) ) ) + { + return E_FAIL; + } + else + { + static const GUID s_wfexBase = {0x00000000, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; + + auto wfex = reinterpret_cast( ptr ); + + if ( memcmp( reinterpret_cast(&wfex->SubFormat) + sizeof(DWORD), + reinterpret_cast(&s_wfexBase) + sizeof(DWORD), sizeof(GUID) - sizeof(DWORD) ) != 0 ) + { + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + switch( wfex->SubFormat.Data1 ) + { + case WAVE_FORMAT_PCM: + case WAVE_FORMAT_IEEE_FLOAT: + break; + + // MS-ADPCM and XMA2 are not supported as WAVEFORMATEXTENSIBLE + + case WAVE_FORMAT_WMAUDIO2: + case WAVE_FORMAT_WMAUDIO3: + dpds = true; + break; + + default: + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + } + break; + + default: + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + } + } + + // Locate 'data' + ptr = reinterpret_cast( riffHeader ) + sizeof(RIFFChunkHeader); + if ( ( ptr + sizeof(RIFFChunk) ) > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + auto dataChunk = FindChunk( ptr, riffChunk->size, FOURCC_DATA_TAG ); + if ( !dataChunk || !dataChunk->size ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + } + + ptr = reinterpret_cast( dataChunk ) + sizeof( RIFFChunk ); + if ( ptr + dataChunk->size > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + *pwfx = reinterpret_cast( wf ); + *pdata = ptr; + *dataSize = dataChunk->size; + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +static HRESULT WaveFindLoopInfo( _In_reads_bytes_(wavDataSize) const uint8_t* wavData, _In_ size_t wavDataSize, + _Out_ uint32_t* pLoopStart, _Out_ uint32_t* pLoopLength ) +{ + if ( !wavData || !pLoopStart || !pLoopLength ) + return E_POINTER; + + if (wavDataSize < ( sizeof(RIFFChunk) + sizeof(uint32_t) ) ) + { + return E_FAIL; + } + + *pLoopStart = 0; + *pLoopLength = 0; + + const uint8_t* wavEnd = wavData + wavDataSize; + + // Locate RIFF 'WAVE' + auto riffChunk = FindChunk( wavData, wavDataSize, FOURCC_RIFF_TAG ); + if ( !riffChunk || riffChunk->size < 4 ) + { + return E_FAIL; + } + + auto riffHeader = reinterpret_cast( riffChunk ); + if ( riffHeader->riff == FOURCC_XWMA_FILE_TAG ) + { + // xWMA files do not contain loop information + return S_OK; + } + + if ( riffHeader->riff != FOURCC_WAVE_FILE_TAG ) + { + return E_FAIL; + } + + // Locate 'wsmp' (DLS Chunk) + auto ptr = reinterpret_cast( riffHeader ) + sizeof(RIFFChunkHeader); + if ( ( ptr + sizeof(RIFFChunk) ) > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + auto dlsChunk = FindChunk( ptr, riffChunk->size, FOURCC_DLS_SAMPLE ); + if ( dlsChunk ) + { + ptr = reinterpret_cast( dlsChunk ) + sizeof( RIFFChunk ); + if ( ptr + dlsChunk->size > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + if ( dlsChunk->size >= sizeof(RIFFDLSSample) ) + { + auto dlsSample = reinterpret_cast( ptr ); + + if ( dlsChunk->size >= ( dlsSample->size + dlsSample->loopCount * sizeof(DLSLoop) ) ) + { + auto loops = reinterpret_cast( ptr + dlsSample->size ); + for( uint32_t j = 0; j < dlsSample->loopCount; ++j ) + { + if ( ( loops[j].loopType == DLSLoop::LOOP_TYPE_FORWARD || loops[j].loopType == DLSLoop::LOOP_TYPE_RELEASE ) ) + { + // Return 'forward' loop + *pLoopStart = loops[j].loopStart; + *pLoopLength = loops[j].loopLength; + return S_OK; + } + } + } + } + } + + // Locate 'smpl' (Sample Chunk) + auto midiChunk = FindChunk( ptr, riffChunk->size, FOURCC_MIDI_SAMPLE ); + if ( midiChunk ) + { + ptr = reinterpret_cast( midiChunk ) + sizeof( RIFFChunk ); + if ( ptr + midiChunk->size > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + if ( midiChunk->size >= sizeof(RIFFMIDISample) ) + { + auto midiSample = reinterpret_cast( ptr ); + + if ( midiChunk->size >= ( sizeof(RIFFMIDISample) + midiSample->loopCount * sizeof(MIDILoop) ) ) + { + auto loops = reinterpret_cast( ptr + sizeof(RIFFMIDISample) ); + for( uint32_t j = 0; j < midiSample->loopCount; ++j ) + { + if ( loops[j].type == MIDILoop::LOOP_TYPE_FORWARD ) + { + // Return 'forward' loop + *pLoopStart = loops[j].start; + *pLoopLength = loops[j].end + loops[j].start + 1; + return S_OK; + } + } + } + } + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +static HRESULT WaveFindTable( _In_reads_bytes_(wavDataSize) const uint8_t* wavData, _In_ size_t wavDataSize, _In_ uint32_t tag, + _Outptr_result_maybenull_ const uint32_t** pData, _Out_ uint32_t* dataCount ) +{ + if ( !wavData || !pData || !dataCount ) + return E_POINTER; + + if (wavDataSize < ( sizeof(RIFFChunk) + sizeof(uint32_t) ) ) + { + return E_FAIL; + } + + *pData = nullptr; + *dataCount = 0; + + const uint8_t* wavEnd = wavData + wavDataSize; + + // Locate RIFF 'WAVE' + auto riffChunk = FindChunk( wavData, wavDataSize, FOURCC_RIFF_TAG ); + if ( !riffChunk || riffChunk->size < 4 ) + { + return E_FAIL; + } + + auto riffHeader = reinterpret_cast( riffChunk ); + if ( riffHeader->riff != FOURCC_WAVE_FILE_TAG && riffHeader->riff != FOURCC_XWMA_FILE_TAG ) + { + return E_FAIL; + } + + // Locate tag + auto ptr = reinterpret_cast( riffHeader ) + sizeof(RIFFChunkHeader); + if ( ( ptr + sizeof(RIFFChunk) ) > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + auto tableChunk = FindChunk( ptr, riffChunk->size, tag ); + if ( tableChunk ) + { + ptr = reinterpret_cast( tableChunk ) + sizeof( RIFFChunk ); + if ( ptr + tableChunk->size > wavEnd ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + if ( ( tableChunk->size % sizeof(uint32_t) ) != 0 ) + { + return E_FAIL; + } + + *pData = reinterpret_cast( ptr ); + *dataCount = tableChunk->size / 4; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +static HRESULT LoadAudioFromFile( _In_z_ const wchar_t* szFileName, _Inout_ std::unique_ptr& wavData, _Out_ DWORD* bytesRead ) +{ + if ( !szFileName ) + return E_INVALIDARG; + + // open the file +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile( safe_handle( CreateFile2( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr ) ) ); +#else + ScopedHandle hFile( safe_handle( CreateFileW( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr ) ) ); +#endif + + if ( !hFile ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // File is too big for 32-bit allocation, so reject read + if (fileInfo.EndOfFile.HighPart > 0) + { + return E_FAIL; + } + + // Need at least enough data to have a valid minimal WAV file + if (fileInfo.EndOfFile.LowPart < ( sizeof(RIFFChunk)*2 + sizeof(DWORD) + sizeof(WAVEFORMAT) ) ) + { + return E_FAIL; + } + + // create enough space for the file data + wavData.reset( new (std::nothrow) uint8_t[ fileInfo.EndOfFile.LowPart ] ); + if (!wavData) + { + return E_OUTOFMEMORY; + } + + // read the data in + if (!ReadFile( hFile.get(), + wavData.get(), + fileInfo.EndOfFile.LowPart, + bytesRead, + nullptr + )) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + return (*bytesRead < fileInfo.EndOfFile.LowPart) ? E_FAIL : S_OK; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWAVAudioInMemory( const uint8_t* wavData, + size_t wavDataSize, + const WAVEFORMATEX** wfx, + const uint8_t** startAudio, + uint32_t* audioBytes ) +{ + if ( !wavData || !wfx || !startAudio || !audioBytes ) + return E_INVALIDARG; + + *wfx = nullptr; + *startAudio = nullptr; + *audioBytes = 0; + + // Need at least enough data to have a valid minimal WAV file + if (wavDataSize < (sizeof(RIFFChunk)*2 + sizeof(DWORD) + sizeof(WAVEFORMAT) ) ) + { + return E_FAIL; + } + + bool dpds, seek; + HRESULT hr = WaveFindFormatAndData( wavData, wavDataSize, wfx, startAudio, audioBytes, dpds, seek ); + if ( FAILED(hr) ) + return hr; + + return (dpds || seek) ? E_FAIL : S_OK; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWAVAudioFromFile( const wchar_t* szFileName, + std::unique_ptr& wavData, + const WAVEFORMATEX** wfx, + const uint8_t** startAudio, + uint32_t* audioBytes ) +{ + if ( !szFileName || !wfx || !startAudio || !audioBytes ) + return E_INVALIDARG; + + *wfx = nullptr; + *startAudio = nullptr; + *audioBytes = 0; + + DWORD bytesRead = 0; + HRESULT hr = LoadAudioFromFile( szFileName, wavData, &bytesRead ); + if ( FAILED(hr) ) + { + return hr; + } + + bool dpds, seek; + hr = WaveFindFormatAndData( wavData.get(), bytesRead, wfx, startAudio, audioBytes, dpds, seek ); + if ( FAILED(hr) ) + return hr; + + return (dpds || seek) ? E_FAIL : S_OK; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWAVAudioInMemoryEx( const uint8_t* wavData, size_t wavDataSize, DirectX::WAVData& result ) +{ + if ( !wavData ) + return E_INVALIDARG; + + memset( &result, 0, sizeof(result) ); + + // Need at least enough data to have a valid minimal WAV file + if (wavDataSize < (sizeof(RIFFChunk)*2 + sizeof(DWORD) + sizeof(WAVEFORMAT) ) ) + { + return E_FAIL; + } + + bool dpds, seek; + HRESULT hr = WaveFindFormatAndData( wavData, wavDataSize, &result.wfx, &result.startAudio, &result.audioBytes, dpds, seek ); + if ( FAILED(hr) ) + return hr; + + hr = WaveFindLoopInfo( wavData, wavDataSize, &result.loopStart, &result.loopLength ); + if ( FAILED(hr) ) + return hr; + + if ( dpds ) + { + hr = WaveFindTable( wavData, wavDataSize, FOURCC_XWMA_DPDS, &result.seek, &result.seekCount ); + if ( FAILED(hr) ) + return hr; + } + else if ( seek ) + { + hr = WaveFindTable( wavData, wavDataSize, FOURCC_XMA_SEEK, &result.seek, &result.seekCount ); + if ( FAILED(hr) ) + return hr; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadWAVAudioFromFileEx( const wchar_t* szFileName, std::unique_ptr& wavData, DirectX::WAVData& result ) +{ + if ( !szFileName ) + return E_INVALIDARG; + + memset( &result, 0, sizeof(result) ); + + DWORD bytesRead = 0; + HRESULT hr = LoadAudioFromFile( szFileName, wavData, &bytesRead ); + if ( FAILED(hr) ) + { + return hr; + } + + bool dpds, seek; + hr = WaveFindFormatAndData( wavData.get(), bytesRead, &result.wfx, &result.startAudio, &result.audioBytes, dpds, seek ); + if ( FAILED(hr) ) + return hr; + + hr = WaveFindLoopInfo( wavData.get(), bytesRead, &result.loopStart, &result.loopLength ); + if ( FAILED(hr) ) + return hr; + + if ( dpds ) + { + hr = WaveFindTable( wavData.get(), bytesRead, FOURCC_XWMA_DPDS, &result.seek, &result.seekCount ); + if ( FAILED(hr) ) + return hr; + } + else if ( seek ) + { + hr = WaveFindTable( wavData.get(), bytesRead, FOURCC_XMA_SEEK, &result.seek, &result.seekCount ); + if ( FAILED(hr) ) + return hr; + } + + return S_OK; +} + diff --git a/Kits/DirectXTK12/Audio/WAVFileReader.h b/Kits/DirectXTK12/Audio/WAVFileReader.h new file mode 100644 index 00000000..1043ce50 --- /dev/null +++ b/Kits/DirectXTK12/Audio/WAVFileReader.h @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------------------------- +// File: WAVFileReader.h +// +// Functions for loading WAV audio files +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include + + +namespace DirectX +{ + HRESULT LoadWAVAudioInMemory( _In_reads_bytes_(wavDataSize) const uint8_t* wavData, + _In_ size_t wavDataSize, + _Outptr_ const WAVEFORMATEX** wfx, + _Outptr_ const uint8_t** startAudio, + _Out_ uint32_t* audioBytes ); + + HRESULT LoadWAVAudioFromFile( _In_z_ const wchar_t* szFileName, + _Inout_ std::unique_ptr& wavData, + _Outptr_ const WAVEFORMATEX** wfx, + _Outptr_ const uint8_t** startAudio, + _Out_ uint32_t* audioBytes ); + + struct WAVData + { + const WAVEFORMATEX* wfx; + const uint8_t* startAudio; + uint32_t audioBytes; + uint32_t loopStart; + uint32_t loopLength; + const uint32_t* seek; // Note: XMA Seek data is Big-Endian + uint32_t seekCount; + }; + + HRESULT LoadWAVAudioInMemoryEx( _In_reads_bytes_(wavDataSize) const uint8_t* wavData, + _In_ size_t wavDataSize, _Out_ WAVData& result ); + + HRESULT LoadWAVAudioFromFileEx( _In_z_ const wchar_t* szFileName, + _Inout_ std::unique_ptr& wavData, + _Out_ WAVData& result ); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Audio/WaveBank.cpp b/Kits/DirectXTK12/Audio/WaveBank.cpp new file mode 100644 index 00000000..64417701 --- /dev/null +++ b/Kits/DirectXTK12/Audio/WaveBank.cpp @@ -0,0 +1,511 @@ +//-------------------------------------------------------------------------------------- +// File: WaveBank.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Audio.h" +#include "WaveBankReader.h" +#include "SoundCommon.h" +#include "PlatformHelpers.h" + +#include + +using namespace DirectX; + + +//====================================================================================== +// WaveBank +//====================================================================================== + +// Internal object implementation class. +class WaveBank::Impl : public IVoiceNotify +{ +public: + explicit Impl( _In_ AudioEngine* engine ) : + mEngine( engine ), + mOneShots( 0 ), + mPrepared( false ), + mStreaming( false ) + { + assert( mEngine != 0 ); + mEngine->RegisterNotify( this, false ); + } + + virtual ~Impl() + { + if ( !mInstances.empty() ) + { + DebugTrace( "WARNING: Destroying WaveBank \"%hs\" with %Iu outstanding SoundEffectInstances\n", mReader.BankName(), mInstances.size() ); + + for( auto it = mInstances.begin(); it != mInstances.end(); ++it ) + { + assert( *it != 0 ); + (*it)->OnDestroyParent(); + } + + mInstances.clear(); + } + + if ( mOneShots > 0 ) + { + DebugTrace( "WARNING: Destroying WaveBank \"%hs\" with %u outstanding one shot effects\n", mReader.BankName(), mOneShots ); + } + + if ( mEngine ) + { + mEngine->UnregisterNotify( this, true, false ); + mEngine = nullptr; + } + } + + HRESULT Initialize( _In_ AudioEngine* engine, _In_z_ const wchar_t* wbFileName ); + + void Play( int index, float volume, float pitch, float pan ); + + // IVoiceNotify + virtual void __cdecl OnBufferEnd() override + { + InterlockedDecrement( &mOneShots ); + } + + virtual void __cdecl OnCriticalError() override + { + mOneShots = 0; + } + + virtual void __cdecl OnReset() override + { + // No action required + } + + virtual void __cdecl OnUpdate() override + { + // We do not register for update notification + assert(false); + } + + virtual void __cdecl OnDestroyEngine() override + { + mEngine = nullptr; + mOneShots = 0; + } + + virtual void __cdecl OnTrim() override + { + // No action required + } + + virtual void __cdecl GatherStatistics( AudioStatistics& stats ) const override + { + stats.playingOneShots += mOneShots; + + if ( !mStreaming ) + { + stats.audioBytes += mReader.BankAudioSize(); + +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( mReader.HasXMA() ) + stats.xmaAudioBytes += mReader.BankAudioSize(); +#endif + } + } + + AudioEngine* mEngine; + std::list mInstances; + WaveBankReader mReader; + uint32_t mOneShots; + bool mPrepared; + bool mStreaming; +}; + + +_Use_decl_annotations_ +HRESULT WaveBank::Impl::Initialize( AudioEngine* engine, const wchar_t* wbFileName ) +{ + if ( !engine || !wbFileName ) + return E_INVALIDARG; + + HRESULT hr = mReader.Open( wbFileName ); + if ( FAILED(hr) ) + return hr; + + mStreaming = mReader.IsStreamingBank(); + + return S_OK; +} + + +void WaveBank::Impl::Play( int index, float volume, float pitch, float pan ) +{ + assert( volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL ); + assert( pitch >= -1.f && pitch <= 1.f ); + assert( pan >= -1.f && pan <= 1.f ); + + if ( mStreaming ) + { + DebugTrace( "ERROR: One-shots can only be created from an in-memory wave bank\n"); + throw std::exception( "WaveBank::Play" ); + } + + if ( index < 0 || uint32_t(index) >= mReader.Count() ) + { + DebugTrace( "WARNING: Index %d not found in wave bank with only %u entries, one-shot not triggered\n", index, mReader.Count() ); + return; + } + + if ( !mPrepared ) + { + mReader.WaitOnPrepare(); + mPrepared = true; + } + + char wfxbuff[64]; + auto wfx = reinterpret_cast( wfxbuff ); + HRESULT hr = mReader.GetFormat( index, wfx, 64 ); + ThrowIfFailed( hr ); + + IXAudio2SourceVoice* voice = nullptr; + mEngine->AllocateVoice( wfx, SoundEffectInstance_Default, true, &voice ); + + if ( !voice ) + return; + + if ( volume != 1.f ) + { + hr = voice->SetVolume( volume ); + ThrowIfFailed( hr ); + } + + if ( pitch != 0.f ) + { + float fr = XAudio2SemitonesToFrequencyRatio( pitch * 12.f ); + + hr = voice->SetFrequencyRatio( fr ); + ThrowIfFailed( hr ); + } + + if ( pan != 0.f ) + { + float matrix[16]; + if ( ComputePan( pan, wfx->nChannels, matrix ) ) + { + hr = voice->SetOutputMatrix( nullptr, wfx->nChannels, mEngine->GetOutputChannels(), matrix ); + ThrowIfFailed( hr ); + } + } + + hr = voice->Start( 0 ); + ThrowIfFailed( hr ); + + XAUDIO2_BUFFER buffer = {}; + hr = mReader.GetWaveData( index, &buffer.pAudioData, buffer.AudioBytes ); + ThrowIfFailed( hr ); + + WaveBankReader::Metadata metadata; + hr = mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + + buffer.Flags = XAUDIO2_END_OF_STREAM; + buffer.pContext = this; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + + XAUDIO2_BUFFER_WMA wmaBuffer = {}; + + uint32_t tag; + hr = mReader.GetSeekTable( index, &wmaBuffer.pDecodedPacketCumulativeBytes, wmaBuffer.PacketCount, tag ); + ThrowIfFailed( hr ); + + if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 ) + { + hr = voice->SubmitSourceBuffer( &buffer, &wmaBuffer ); + } + else +#endif + { + hr = voice->SubmitSourceBuffer( &buffer, nullptr ); + } + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: WaveBank failed (%08X) when submitting buffer:\n", hr ); + DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %u bytes\n", wfx->wFormatTag, + wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec, metadata.lengthBytes ); + throw std::exception( "SubmitSourceBuffer" ); + } + + InterlockedIncrement( &mOneShots ); +} + + +//-------------------------------------------------------------------------------------- +// WaveBank +//-------------------------------------------------------------------------------------- + +// Public constructors. +_Use_decl_annotations_ +WaveBank::WaveBank( AudioEngine* engine, const wchar_t* wbFileName ) + : pImpl(new Impl(engine) ) +{ + HRESULT hr = pImpl->Initialize( engine, wbFileName ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: WaveBank failed (%08X) to intialize from .xwb file \"%ls\"\n", hr, wbFileName ); + throw std::exception( "WaveBank" ); + } + + DebugTrace( "INFO: WaveBank \"%hs\" with %u entries loaded from .xwb file \"%ls\"\n", + pImpl->mReader.BankName(), pImpl->mReader.Count(), wbFileName ); +} + + +// Move constructor. +WaveBank::WaveBank(WaveBank&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +WaveBank& WaveBank::operator= (WaveBank&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +WaveBank::~WaveBank() +{ +} + + +// Public methods. +void WaveBank::Play( int index ) +{ + pImpl->Play( index, 1.f, 0.f, 0.f ); +} + + +void WaveBank::Play( int index, float volume, float pitch, float pan ) +{ + pImpl->Play( index, volume, pitch, pan ); +} + + +void WaveBank::Play( _In_z_ const char* name ) +{ + int index = static_cast( pImpl->mReader.Find( name ) ); + if ( index == -1 ) + { + DebugTrace( "WARNING: Name '%hs' not found in wave bank, one-shot not triggered\n", name ); + return; + } + + pImpl->Play( index, 1.f, 0.f, 0.f ); +} + + +void WaveBank::Play( _In_z_ const char* name, float volume, float pitch, float pan ) +{ + int index = static_cast( pImpl->mReader.Find( name ) ); + if ( index == -1 ) + { + DebugTrace( "WARNING: Name '%hs' not found in wave bank, one-shot not triggered\n", name ); + return; + } + + pImpl->Play( index, volume, pitch, pan ); +} + + +std::unique_ptr WaveBank::CreateInstance( int index, SOUND_EFFECT_INSTANCE_FLAGS flags ) +{ + auto& wb = pImpl->mReader; + + if ( pImpl->mStreaming ) + { + DebugTrace( "ERROR: SoundEffectInstances can only be created from an in-memory wave bank\n"); + throw std::exception( "WaveBank::CreateInstance" ); + } + + if ( index < 0 || uint32_t(index) >= wb.Count() ) + { + // We don't throw an exception here as titles often simply ignore missing assets rather than fail + return std::unique_ptr(); + } + + if ( !pImpl->mPrepared ) + { + wb.WaitOnPrepare(); + pImpl->mPrepared = true; + } + + auto effect = new SoundEffectInstance( pImpl->mEngine, this, index, flags ); + assert( effect != 0 ); + pImpl->mInstances.emplace_back( effect ); + return std::unique_ptr( effect ); +} + + +std::unique_ptr WaveBank::CreateInstance( _In_z_ const char* name, SOUND_EFFECT_INSTANCE_FLAGS flags ) +{ + int index = static_cast( pImpl->mReader.Find( name ) ); + if ( index == -1 ) + { + // We don't throw an exception here as titles often simply ignore missing assets rather than fail + return std::unique_ptr(); + } + + return CreateInstance( index, flags ); +} + + +void WaveBank::UnregisterInstance( _In_ SoundEffectInstance* instance ) +{ + auto it = std::find( pImpl->mInstances.begin(), pImpl->mInstances.end(), instance ); + if ( it == pImpl->mInstances.end() ) + return; + + pImpl->mInstances.erase( it ); +} + + +// Public accessors. +bool WaveBank::IsPrepared() const +{ + if ( pImpl->mPrepared ) + return true; + + if ( !pImpl->mReader.IsPrepared() ) + return false; + + pImpl->mPrepared = true; + return true; +} + + +bool WaveBank::IsInUse() const +{ + return ( pImpl->mOneShots > 0 ) || !pImpl->mInstances.empty(); +} + + +bool WaveBank::IsStreamingBank() const +{ + return pImpl->mReader.IsStreamingBank(); +} + + +size_t WaveBank::GetSampleSizeInBytes( int index ) const +{ + if ( index < 0 || uint32_t(index) >= pImpl->mReader.Count() ) + return 0; + + WaveBankReader::Metadata metadata; + HRESULT hr = pImpl->mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + return metadata.lengthBytes; +} + + +size_t WaveBank::GetSampleDuration( int index ) const +{ + if ( index < 0 || uint32_t(index) >= pImpl->mReader.Count() ) + return 0; + + WaveBankReader::Metadata metadata; + HRESULT hr = pImpl->mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + return metadata.duration; +} + + +size_t WaveBank::GetSampleDurationMS( int index ) const +{ + if ( index < 0 || uint32_t(index) >= pImpl->mReader.Count() ) + return 0; + + char buff[64]; + auto wfx = reinterpret_cast( buff ); + HRESULT hr = pImpl->mReader.GetFormat( index, wfx, 64 ); + ThrowIfFailed( hr ); + + WaveBankReader::Metadata metadata; + hr = pImpl->mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + return static_cast( ( uint64_t(metadata.duration) * 1000 ) / wfx->nSamplesPerSec ); +} + + +_Use_decl_annotations_ +const WAVEFORMATEX* WaveBank::GetFormat( int index, WAVEFORMATEX* wfx, size_t maxsize ) const +{ + if ( index < 0 || uint32_t(index) >= pImpl->mReader.Count() ) + return nullptr; + + HRESULT hr = pImpl->mReader.GetFormat( index, wfx, maxsize ); + ThrowIfFailed( hr ); + return wfx; +} + + +_Use_decl_annotations_ +int WaveBank::Find( const char* name ) const +{ + return static_cast( pImpl->mReader.Find( name ) ); +} + + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +_Use_decl_annotations_ +bool WaveBank::FillSubmitBuffer( int index, XAUDIO2_BUFFER& buffer, XAUDIO2_BUFFER_WMA& wmaBuffer ) const +{ + memset( &buffer, 0, sizeof(buffer) ); + memset( &wmaBuffer, 0, sizeof(wmaBuffer) ); + + HRESULT hr = pImpl->mReader.GetWaveData( index, &buffer.pAudioData, buffer.AudioBytes ); + ThrowIfFailed( hr ); + + WaveBankReader::Metadata metadata; + hr = pImpl->mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + + buffer.LoopBegin = metadata.loopStart; + buffer.LoopLength = metadata.loopLength; + + uint32_t tag; + hr = pImpl->mReader.GetSeekTable( index, &wmaBuffer.pDecodedPacketCumulativeBytes, wmaBuffer.PacketCount, tag ); + ThrowIfFailed( hr ); + + return ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 ); +} + +#else + +_Use_decl_annotations_ +void WaveBank::FillSubmitBuffer( int index, XAUDIO2_BUFFER& buffer ) const +{ + memset( &buffer, 0, sizeof(buffer) ); + + HRESULT hr = pImpl->mReader.GetWaveData( index, &buffer.pAudioData, buffer.AudioBytes ); + ThrowIfFailed( hr ); + + WaveBankReader::Metadata metadata; + hr = pImpl->mReader.GetMetadata( index, metadata ); + ThrowIfFailed( hr ); + + buffer.LoopBegin = metadata.loopStart; + buffer.LoopLength = metadata.loopLength; +} + +#endif diff --git a/Kits/DirectXTK12/Audio/WaveBankReader.cpp b/Kits/DirectXTK12/Audio/WaveBankReader.cpp new file mode 100644 index 00000000..924325c7 --- /dev/null +++ b/Kits/DirectXTK12/Audio/WaveBankReader.cpp @@ -0,0 +1,1376 @@ +//-------------------------------------------------------------------------------------- +// File: WaveBankReader.cpp +// +// Functions for loading audio data from Wave Banks +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#include "pch.h" +#include "WaveBankReader.h" +#include "Audio.h" +#include "PlatformHelpers.h" + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#endif + + +namespace +{ + +//-------------------------------------------------------------------------------------- +#pragma pack(push, 1) + +static const size_t DVD_SECTOR_SIZE = 2048; +static const size_t DVD_BLOCK_SIZE = DVD_SECTOR_SIZE * 16; + +static const size_t ALIGNMENT_MIN = 4; +static const size_t ALIGNMENT_DVD = DVD_SECTOR_SIZE; + +static const size_t MAX_DATA_SEGMENT_SIZE = 0xFFFFFFFF; +static const size_t MAX_COMPACT_DATA_SEGMENT_SIZE = 0x001FFFFF; + +struct REGION +{ + uint32_t dwOffset; // Region offset, in bytes. + uint32_t dwLength; // Region length, in bytes. + + void BigEndian() + { + dwOffset = _byteswap_ulong( dwOffset ); + dwLength = _byteswap_ulong( dwLength ); + } +}; + +struct SAMPLEREGION +{ + uint32_t dwStartSample; // Start sample for the region. + uint32_t dwTotalSamples; // Region length in samples. + + void BigEndian() + { + dwStartSample = _byteswap_ulong( dwStartSample ); + dwTotalSamples = _byteswap_ulong( dwTotalSamples ); + } +}; + +struct HEADER +{ + static const uint32_t SIGNATURE = 'DNBW'; + static const uint32_t BE_SIGNATURE = 'WBND'; + static const uint32_t VERSION = 44; + + enum SEGIDX + { + SEGIDX_BANKDATA = 0, // Bank data + SEGIDX_ENTRYMETADATA, // Entry meta-data + SEGIDX_SEEKTABLES, // Storage for seek tables for the encoded waves. + SEGIDX_ENTRYNAMES, // Entry friendly names + SEGIDX_ENTRYWAVEDATA, // Entry wave data + SEGIDX_COUNT + }; + + uint32_t dwSignature; // File signature + uint32_t dwVersion; // Version of the tool that created the file + uint32_t dwHeaderVersion; // Version of the file format + REGION Segments[SEGIDX_COUNT]; // Segment lookup table + + void BigEndian() + { + // Leave dwSignature alone as indicator of BE vs. LE + + dwVersion = _byteswap_ulong( dwVersion ); + dwHeaderVersion =_byteswap_ulong( dwHeaderVersion ); + for( size_t j = 0; j < SEGIDX_COUNT; ++j ) + { + Segments[j].BigEndian(); + } + } +}; + +#pragma warning( disable : 4201 4203 ) + +union MINIWAVEFORMAT +{ + static const uint32_t TAG_PCM = 0x0; + static const uint32_t TAG_XMA = 0x1; + static const uint32_t TAG_ADPCM = 0x2; + static const uint32_t TAG_WMA = 0x3; + + static const uint32_t BITDEPTH_8 = 0x0; // PCM only + static const uint32_t BITDEPTH_16 = 0x1; // PCM only + + static const size_t ADPCM_BLOCKALIGN_CONVERSION_OFFSET = 22; + + struct + { + uint32_t wFormatTag : 2; // Format tag + uint32_t nChannels : 3; // Channel count (1 - 6) + uint32_t nSamplesPerSec : 18; // Sampling rate + uint32_t wBlockAlign : 8; // Block alignment. For WMA, lower 6 bits block alignment index, upper 2 bits bytes-per-second index. + uint32_t wBitsPerSample : 1; // Bits per sample (8 vs. 16, PCM only); WMAudio2/WMAudio3 (for WMA) + }; + + uint32_t dwValue; + + void BigEndian() + { + dwValue = _byteswap_ulong( dwValue ); + } + + WORD BitsPerSample() const + { + if (wFormatTag == TAG_XMA) + return 16; // XMA_OUTPUT_SAMPLE_BITS == 16 + if (wFormatTag == TAG_WMA) + return 16; + if (wFormatTag == TAG_ADPCM) + return 4; // MSADPCM_BITS_PER_SAMPLE == 4 + + // wFormatTag must be TAG_PCM (2 bits can only represent 4 different values) + return (wBitsPerSample == BITDEPTH_16) ? 16 : 8; + } + + DWORD BlockAlign() const + { + switch (wFormatTag) + { + case TAG_PCM: + return wBlockAlign; + + case TAG_XMA: + return (nChannels * 16 / 8); // XMA_OUTPUT_SAMPLE_BITS = 16 + + case TAG_ADPCM: + return (wBlockAlign + ADPCM_BLOCKALIGN_CONVERSION_OFFSET) * nChannels; + + case TAG_WMA: + { + static const uint32_t aWMABlockAlign[] = + { + 929, + 1487, + 1280, + 2230, + 8917, + 8192, + 4459, + 5945, + 2304, + 1536, + 1485, + 1008, + 2731, + 4096, + 6827, + 5462, + 1280 + }; + + uint32_t dwBlockAlignIndex = wBlockAlign & 0x1F; + if ( dwBlockAlignIndex < _countof(aWMABlockAlign) ) + return aWMABlockAlign[dwBlockAlignIndex]; + } + break; + } + + return 0; + } + + DWORD AvgBytesPerSec() const + { + switch (wFormatTag) + { + case TAG_PCM: + return nSamplesPerSec * wBlockAlign; + + case TAG_XMA: + return nSamplesPerSec * BlockAlign(); + + case TAG_ADPCM: + { + uint32_t blockAlign = BlockAlign(); + uint32_t samplesPerAdpcmBlock = AdpcmSamplesPerBlock(); + return blockAlign * nSamplesPerSec / samplesPerAdpcmBlock; + } + break; + + case TAG_WMA: + { + static const uint32_t aWMAAvgBytesPerSec[] = + { + 12000, + 24000, + 4000, + 6000, + 8000, + 20000, + 2500 + }; + // bitrate = entry * 8 + + uint32_t dwBytesPerSecIndex = wBlockAlign >> 5; + if ( dwBytesPerSecIndex < _countof(aWMAAvgBytesPerSec) ) + return aWMAAvgBytesPerSec[dwBytesPerSecIndex]; + } + break; + } + + return 0; + } + + DWORD AdpcmSamplesPerBlock() const + { + uint32_t nBlockAlign = (wBlockAlign + ADPCM_BLOCKALIGN_CONVERSION_OFFSET) * nChannels; + return nBlockAlign * 2 / (uint32_t)nChannels - 12; + } + + void AdpcmFillCoefficientTable(ADPCMWAVEFORMAT *fmt) const + { + // These are fixed since we are always using MS ADPCM + fmt->wNumCoef = 7 /* MSADPCM_NUM_COEFFICIENTS */; + + static ADPCMCOEFSET aCoef[7] = { { 256, 0}, {512, -256}, {0,0}, {192,64}, {240,0}, {460, -208}, {392,-232} }; + memcpy( &fmt->aCoef, aCoef, sizeof(aCoef) ); + } +}; + +struct BANKDATA +{ + static const size_t BANKNAME_LENGTH = 64; + + static const uint32_t TYPE_BUFFER = 0x00000000; + static const uint32_t TYPE_STREAMING = 0x00000001; + static const uint32_t TYPE_MASK = 0x00000001; + + static const uint32_t FLAGS_ENTRYNAMES = 0x00010000; + static const uint32_t FLAGS_COMPACT = 0x00020000; + static const uint32_t FLAGS_SYNC_DISABLED = 0x00040000; + static const uint32_t FLAGS_SEEKTABLES = 0x00080000; + static const uint32_t FLAGS_MASK = 0x000F0000; + + uint32_t dwFlags; // Bank flags + uint32_t dwEntryCount; // Number of entries in the bank + char szBankName[BANKNAME_LENGTH]; // Bank friendly name + uint32_t dwEntryMetaDataElementSize; // Size of each entry meta-data element, in bytes + uint32_t dwEntryNameElementSize; // Size of each entry name element, in bytes + uint32_t dwAlignment; // Entry alignment, in bytes + MINIWAVEFORMAT CompactFormat; // Format data for compact bank + FILETIME BuildTime; // Build timestamp + + void BigEndian() + { + dwFlags = _byteswap_ulong( dwFlags ); + dwEntryCount = _byteswap_ulong( dwEntryCount ); + dwEntryMetaDataElementSize = _byteswap_ulong( dwEntryMetaDataElementSize ); + dwEntryNameElementSize = _byteswap_ulong( dwEntryNameElementSize ); + dwAlignment = _byteswap_ulong( dwAlignment ); + CompactFormat.BigEndian(); + BuildTime.dwLowDateTime = _byteswap_ulong( BuildTime.dwLowDateTime ); + BuildTime.dwHighDateTime = _byteswap_ulong( BuildTime.dwHighDateTime ); + } +}; + +struct ENTRY +{ + static const uint32_t FLAGS_READAHEAD = 0x00000001; // Enable stream read-ahead + static const uint32_t FLAGS_LOOPCACHE = 0x00000002; // One or more looping sounds use this wave + static const uint32_t FLAGS_REMOVELOOPTAIL = 0x00000004;// Remove data after the end of the loop region + static const uint32_t FLAGS_IGNORELOOP = 0x00000008; // Used internally when the loop region can't be used + static const uint32_t FLAGS_MASK = 0x00000008; + + union + { + struct + { + // Entry flags + uint32_t dwFlags : 4; + + // Duration of the wave, in units of one sample. + // For instance, a ten second long wave sampled + // at 48KHz would have a duration of 480,000. + // This value is not affected by the number of + // channels, the number of bits per sample, or the + // compression format of the wave. + uint32_t Duration : 28; + }; + uint32_t dwFlagsAndDuration; + }; + + MINIWAVEFORMAT Format; // Entry format. + REGION PlayRegion; // Region within the wave data segment that contains this entry. + SAMPLEREGION LoopRegion; // Region within the wave data (in samples) that should loop. + + void BigEndian() + { + dwFlagsAndDuration = _byteswap_ulong( dwFlagsAndDuration ); + Format.BigEndian(); + PlayRegion.BigEndian(); + LoopRegion.BigEndian(); + } +}; + +struct ENTRYCOMPACT +{ + uint32_t dwOffset : 21; // Data offset, in multiplies of the bank alignment + uint32_t dwLengthDeviation : 11; // Data length deviation, in bytes + + void BigEndian() + { + *reinterpret_cast( this ) = _byteswap_ulong( *reinterpret_cast( this ) ); + } + + void ComputeLocations( DWORD& offset, DWORD& length, uint32_t index, const HEADER& header, const BANKDATA& data, const ENTRYCOMPACT* entries ) const + { + offset = dwOffset * data.dwAlignment; + + if ( index < ( data.dwEntryCount - 1 ) ) + { + length = ( entries[index + 1].dwOffset * data.dwAlignment ) - offset - dwLengthDeviation; + } + else + { + length = header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength - offset - dwLengthDeviation; + } + } + + static uint32_t GetDuration( DWORD length, const BANKDATA& data, const uint32_t* seekTable ) + { + switch( data.CompactFormat.wFormatTag ) + { + case MINIWAVEFORMAT::TAG_ADPCM: + { + uint32_t duration = ( length / data.CompactFormat.BlockAlign() ) * data.CompactFormat.AdpcmSamplesPerBlock(); + uint32_t partial = length % data.CompactFormat.BlockAlign(); + if ( partial ) + { + if ( partial >= ( 7 * data.CompactFormat.nChannels ) ) + duration += ( partial * 2 / data.CompactFormat.nChannels - 12 ); + } + return duration; + } + + case MINIWAVEFORMAT::TAG_WMA: + if ( seekTable ) + { + uint32_t seekCount = *seekTable; + if ( seekCount > 0 ) + { + return seekTable[ seekCount ] / uint32_t( 2 * data.CompactFormat.nChannels ); + } + } + return 0; + + case MINIWAVEFORMAT::TAG_XMA: + if ( seekTable ) + { + uint32_t seekCount = *seekTable; + if ( seekCount > 0 ) + { + return seekTable[ seekCount ]; + } + } + return 0; + + default: + return uint32_t( ( uint64_t( length ) * 8 ) + / uint64_t( data.CompactFormat.BitsPerSample() * data.CompactFormat.nChannels ) ); + } + } +}; + +#pragma pack(pop) + +inline const uint32_t* FindSeekTable( uint32_t index, const uint8_t* seekTable, const HEADER& header, const BANKDATA& data ) +{ + if ( !seekTable || index >= data.dwEntryCount ) + return nullptr; + + uint32_t seekSize = header.Segments[HEADER::SEGIDX_SEEKTABLES].dwLength; + + if ( ( index * sizeof(uint32_t) ) > seekSize ) + return nullptr; + + auto table = reinterpret_cast( seekTable ); + uint32_t offset = table[ index ]; + if ( offset == uint32_t(-1) ) + return nullptr; + + offset += sizeof(uint32_t) * data.dwEntryCount; + + if ( offset > seekSize ) + return nullptr; + + return reinterpret_cast( seekTable + offset ); +} + +}; + +static_assert( sizeof(REGION)==8, "Mismatch with xact3wb.h" ); +static_assert( sizeof(SAMPLEREGION)==8, "Mismatch with xact3wb.h" ); +static_assert( sizeof(HEADER)==52, "Mismatch with xact3wb.h" ); +static_assert( sizeof(ENTRY)==24, "Mismatch with xact3wb.h" ); +static_assert( sizeof(MINIWAVEFORMAT)==4, "Mismatch with xact3wb.h" ); +static_assert( sizeof(ENTRY)==24, "Mismatch with xact3wb.h" ); +static_assert( sizeof(ENTRYCOMPACT)==4, "Mismatch with xact3wb.h" ); +static_assert( sizeof(BANKDATA)==96, "Mismatch with xact3wb.h" ); + +using namespace DirectX; + +//-------------------------------------------------------------------------------------- +class WaveBankReader::Impl +{ +public: + Impl() : + m_async( INVALID_HANDLE_VALUE ), + m_prepared(false) +#if defined(_XBOX_ONE) && defined(_TITLE) + , m_xmaMemory(nullptr) +#endif + { + memset( &m_header, 0, sizeof(HEADER) ); + memset( &m_data, 0, sizeof(BANKDATA) ); + memset( &m_request, 0, sizeof(OVERLAPPED) ); + } + + ~Impl() { Close(); } + + HRESULT Open( _In_z_ const wchar_t* szFileName ); + void Close(); + + HRESULT GetFormat( _In_ uint32_t index, _Out_writes_bytes_(maxsize) WAVEFORMATEX* pFormat, _In_ size_t maxsize ) const; + + HRESULT GetWaveData( _In_ uint32_t index, _Outptr_ const uint8_t** pData, _Out_ uint32_t& dataSize ) const; + + HRESULT GetSeekTable( _In_ uint32_t index, _Out_ const uint32_t** pData, _Out_ uint32_t& dataCount, _Out_ uint32_t& tag ) const; + + HRESULT GetMetadata( _In_ uint32_t index, _Out_ Metadata& metadata ) const; + + bool UpdatePrepared(); + + void Clear() + { + memset( &m_header, 0, sizeof(HEADER) ); + memset( &m_data, 0, sizeof(BANKDATA ) ); + + m_names.clear(); + m_entries.reset(); + m_seekData.reset(); + m_waveData.reset(); + +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( m_xmaMemory ) + { + ApuFree( m_xmaMemory ); + m_xmaMemory = nullptr; + } +#endif + } + + HANDLE m_async; + ScopedHandle m_event; + OVERLAPPED m_request; + bool m_prepared; + + HEADER m_header; + BANKDATA m_data; + std::map m_names; + +private: + std::unique_ptr m_entries; + std::unique_ptr m_seekData; + std::unique_ptr m_waveData; + +#if defined(_XBOX_ONE) && defined(_TITLE) +public: + void* m_xmaMemory; +#endif +}; + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Impl::Open( const wchar_t* szFileName ) +{ + Close(); + Clear(); + + m_prepared = false; + + m_event.reset( CreateEventEx( nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !m_event ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + CREATEFILE2_EXTENDED_PARAMETERS params = { sizeof(CREATEFILE2_EXTENDED_PARAMETERS), 0 }; + params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + params.dwFileFlags = FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN; + ScopedHandle hFile( safe_handle( CreateFile2( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + ¶ms ) ) ); +#else + ScopedHandle hFile( safe_handle( CreateFileW( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, + nullptr ) ) ); +#endif + + if ( !hFile ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // Read and verify header + OVERLAPPED request = {}; + request.hEvent = m_event.get(); + + bool wait = false; + if( !ReadFile( hFile.get(), &m_header, sizeof( m_header ), nullptr, &request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + wait = true; + } + + DWORD bytes; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + BOOL result = GetOverlappedResultEx( hFile.get(), &request, &bytes, INFINITE, FALSE ); +#else + if ( wait ) + (void)WaitForSingleObject( m_event.get(), INFINITE ); + + BOOL result = GetOverlappedResult( hFile.get(), &request, &bytes, FALSE ); +#endif + + if ( !result || ( bytes != sizeof( m_header ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( m_header.dwSignature != HEADER::SIGNATURE && m_header.dwSignature != HEADER::BE_SIGNATURE ) + { + return E_FAIL; + } + + bool be = ( m_header.dwSignature == HEADER::BE_SIGNATURE ); + if ( be ) + { + DebugTrace( "INFO: \"%ls\" is a big-endian (Xbox 360) wave bank\n", szFileName ); + m_header.BigEndian(); + } + + if ( m_header.dwHeaderVersion != HEADER::VERSION ) + { + return E_FAIL; + } + + // Load bank data + memset( &request, 0, sizeof(request) ); + request.Offset = m_header.Segments[HEADER::SEGIDX_BANKDATA].dwOffset; + request.hEvent = m_event.get(); + + wait = false; + if( !ReadFile( hFile.get(), &m_data, sizeof( m_data ), nullptr, &request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + wait = true; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + result = GetOverlappedResultEx( hFile.get(), &request, &bytes, INFINITE, FALSE ); +#else + if ( wait ) + (void)WaitForSingleObject( m_event.get(), INFINITE ); + + result = GetOverlappedResult( hFile.get(), &request, &bytes, FALSE ); +#endif + + if ( !result || ( bytes != sizeof( m_data ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( be ) + m_data.BigEndian(); + + if ( !m_data.dwEntryCount ) + { + return HRESULT_FROM_WIN32( ERROR_NO_DATA ); + } + + if ( m_data.dwFlags & BANKDATA::TYPE_STREAMING ) + { + if ( m_data.dwAlignment < ALIGNMENT_DVD ) + return E_FAIL; + if ( m_data.dwAlignment % DVD_SECTOR_SIZE ) + return E_FAIL; + } + else if ( m_data.dwAlignment < ALIGNMENT_MIN ) + { + return E_FAIL; + } + + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + if ( m_data.dwEntryMetaDataElementSize != sizeof(ENTRYCOMPACT) ) + { + return E_FAIL; + } + + if ( m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength > ( MAX_COMPACT_DATA_SEGMENT_SIZE * m_data.dwAlignment ) ) + { + // Data segment is too large to be valid compact wavebank + return E_FAIL; + } + } + else + { + if ( m_data.dwEntryMetaDataElementSize != sizeof(ENTRY) ) + { + return E_FAIL; + } + } + + DWORD metadataBytes = m_header.Segments[HEADER::SEGIDX_ENTRYMETADATA].dwLength; + if ( metadataBytes != ( m_data.dwEntryCount * m_data.dwEntryMetaDataElementSize ) ) + { + return E_FAIL; + } + + // Load names + DWORD namesBytes = m_header.Segments[HEADER::SEGIDX_ENTRYNAMES].dwLength; + if ( namesBytes > 0 ) + { + if ( namesBytes >= ( m_data.dwEntryNameElementSize * m_data.dwEntryCount ) ) + { + std::unique_ptr temp( new (std::nothrow) char[ namesBytes ] ); + if ( !temp ) + return E_OUTOFMEMORY; + + memset( &request, 0, sizeof(request) ); + request.Offset = m_header.Segments[HEADER::SEGIDX_ENTRYNAMES].dwOffset; + request.hEvent = m_event.get(); + + wait = false; + if ( !ReadFile( hFile.get(), temp.get(), namesBytes, nullptr, &request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + wait = true; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + result = GetOverlappedResultEx( hFile.get(), &request, &bytes, INFINITE, FALSE ); +#else + if ( wait ) + (void)WaitForSingleObject( m_event.get(), INFINITE ); + + result = GetOverlappedResult( hFile.get(), &request, &bytes, FALSE ); +#endif + + if ( !result || ( namesBytes != bytes ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + for( uint32_t j = 0; j < m_data.dwEntryCount; ++j ) + { + DWORD n = m_data.dwEntryNameElementSize * j; + + char name[ 64 ] = {}; + strncpy_s( name, &temp[ n ], 64 ); + + m_names[ name ] = j; + } + } + } + + // Load entries + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + m_entries.reset( reinterpret_cast( new (std::nothrow) ENTRYCOMPACT[ m_data.dwEntryCount ] ) ); + } + else + { + m_entries.reset( reinterpret_cast( new (std::nothrow) ENTRY[ m_data.dwEntryCount ] ) ); + } + if ( !m_entries ) + return E_OUTOFMEMORY; + + memset( &request, 0, sizeof(request) ); + request.Offset = m_header.Segments[HEADER::SEGIDX_ENTRYMETADATA].dwOffset; + request.hEvent = m_event.get(); + + wait = false; + if ( !ReadFile( hFile.get(), m_entries.get(), metadataBytes, nullptr, &request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + wait = true; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + result = GetOverlappedResultEx( hFile.get(), &request, &bytes, INFINITE, FALSE ); +#else + if ( wait ) + (void)WaitForSingleObject( m_event.get(), INFINITE ); + + result = GetOverlappedResult( hFile.get(), &request, &bytes, FALSE ); +#endif + + if ( !result || ( metadataBytes != bytes ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( be ) + { + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + auto ptr = reinterpret_cast( m_entries.get() ); + for( size_t j = 0; j < m_data.dwEntryCount; ++j, ++ptr ) + ptr->BigEndian(); + } + else + { + auto ptr = reinterpret_cast( m_entries.get() ); + for( size_t j = 0; j < m_data.dwEntryCount; ++j, ++ptr ) + ptr->BigEndian(); + } + } + + // Load seek tables (XMA2 / xWMA) + DWORD seekLen = m_header.Segments[HEADER::SEGIDX_SEEKTABLES].dwLength; + if ( seekLen > 0 ) + { + m_seekData.reset( new (std::nothrow) uint8_t[ seekLen ] ); + if ( !m_seekData ) + return E_OUTOFMEMORY; + + memset( &request, 0, sizeof(OVERLAPPED) ); + request.Offset = m_header.Segments[HEADER::SEGIDX_SEEKTABLES].dwOffset; + request.hEvent = m_event.get(); + + wait = false; + if ( !ReadFile( hFile.get(), m_seekData.get(), seekLen, nullptr, &request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + wait = true; + } + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + result = GetOverlappedResultEx( hFile.get(), &request, &bytes, INFINITE, FALSE ); +#else + if ( wait ) + (void)WaitForSingleObject( m_event.get(), INFINITE ); + + result = GetOverlappedResult( hFile.get(), &request, &bytes, FALSE ); +#endif + + if ( !result || ( seekLen != bytes ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( be ) + { + auto ptr = reinterpret_cast( m_seekData.get() ); + for( size_t j = 0; j < seekLen; j += 4, ++ptr ) + { + *ptr = _byteswap_ulong( *ptr ); + } + } + } + + DWORD waveLen = m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength; + if ( !waveLen ) + { + return HRESULT_FROM_WIN32( ERROR_NO_DATA ); + } + + if ( m_data.dwFlags & BANKDATA::TYPE_STREAMING ) + { + // If streaming, reopen without buffering + hFile.reset(); + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + CREATEFILE2_EXTENDED_PARAMETERS params2 = { sizeof(CREATEFILE2_EXTENDED_PARAMETERS), 0 }; + params2.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + params2.dwFileFlags = FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING; + m_async = CreateFile2( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + ¶ms2 ); +#else + m_async = CreateFileW( szFileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, + nullptr ); +#endif + + if ( m_async == INVALID_HANDLE_VALUE ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + m_prepared = true; + } + else + { + // If in-memory, kick off read of wave data + void *dest; + +#if defined(_XBOX_ONE) && defined(_TITLE) + bool xma = false; + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + if ( m_data.CompactFormat.wFormatTag == MINIWAVEFORMAT::TAG_XMA ) + xma = true; + } + else + { + for( uint32_t j = 0; j < m_data.dwEntryCount; ++j ) + { + auto& entry = reinterpret_cast( m_entries.get() )[ j ]; + if ( entry.Format.wFormatTag == MINIWAVEFORMAT::TAG_XMA ) + { + xma = true; + break; + } + } + } + + if ( xma ) + { + HRESULT hr = ApuAlloc( &m_xmaMemory, nullptr, waveLen, SHAPE_XMA_INPUT_BUFFER_ALIGNMENT ); + if ( FAILED(hr) ) + { + DebugTrace( "ERROR: ApuAlloc failed. Did you allocate a large enough heap with ApuCreateHeap for all your XMA wave data?\n" ); + return hr; + } + + dest = m_xmaMemory; + } + else +#endif // _XBOX_ONE && _TITLE + { + m_waveData.reset( new (std::nothrow) uint8_t[ waveLen ] ); + if ( !m_waveData ) + return E_OUTOFMEMORY; + + dest = m_waveData.get(); + } + + memset( &m_request, 0, sizeof(OVERLAPPED) ); + m_request.Offset = m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwOffset; + m_request.hEvent = m_event.get(); + + if ( !ReadFile( hFile.get(), dest, waveLen, nullptr, &m_request ) ) + { + DWORD error = GetLastError(); + if ( error != ERROR_IO_PENDING ) + return HRESULT_FROM_WIN32( error ); + } + else + { + m_prepared = true; + memset( &m_request, 0, sizeof(OVERLAPPED) ); + } + + m_async = hFile.release(); + } + + return S_OK; +} + + +void WaveBankReader::Impl::Close() +{ + if ( m_async != INVALID_HANDLE_VALUE ) + { + if ( m_request.hEvent != 0 ) + { + DWORD bytes; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + (void)GetOverlappedResultEx( m_async, &m_request, &bytes, INFINITE, FALSE ); +#else + (void)WaitForSingleObject( m_request.hEvent, INFINITE ); + + (void)GetOverlappedResult( m_async, &m_request, &bytes, FALSE ); +#endif + } + + CloseHandle( m_async ); + m_async = INVALID_HANDLE_VALUE; + } + m_event.reset(); + +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( m_xmaMemory ) + { + ApuFree( m_xmaMemory ); + m_xmaMemory = nullptr; + } +#endif +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Impl::GetFormat( uint32_t index, WAVEFORMATEX* pFormat, size_t maxsize ) const +{ + if ( !pFormat || !maxsize ) + return E_INVALIDARG; + + if ( index >= m_data.dwEntryCount || !m_entries ) + { + return E_FAIL; + } + + auto& miniFmt = ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) ? m_data.CompactFormat : ( reinterpret_cast( m_entries.get() )[ index ].Format ); + + switch( miniFmt.wFormatTag ) + { + case MINIWAVEFORMAT::TAG_PCM: + if ( maxsize < sizeof(PCMWAVEFORMAT) ) + return HRESULT_FROM_WIN32( ERROR_MORE_DATA ); + + pFormat->wFormatTag = WAVE_FORMAT_PCM; + + if ( maxsize >= sizeof(WAVEFORMATEX) ) + { + pFormat->cbSize = 0; + } + break; + + case MINIWAVEFORMAT::TAG_ADPCM: + if ( maxsize < ( sizeof(WAVEFORMATEX) + 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/ ) ) + return HRESULT_FROM_WIN32( ERROR_MORE_DATA ); + + pFormat->wFormatTag = WAVE_FORMAT_ADPCM; + pFormat->cbSize = 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/; + { + auto adpcmFmt = reinterpret_cast(pFormat); + adpcmFmt->wSamplesPerBlock = (WORD) miniFmt.AdpcmSamplesPerBlock(); + miniFmt.AdpcmFillCoefficientTable( adpcmFmt ); + } + break; + + case MINIWAVEFORMAT::TAG_WMA: + if ( maxsize < sizeof(WAVEFORMATEX) ) + return HRESULT_FROM_WIN32( ERROR_MORE_DATA ); + + pFormat->wFormatTag = (miniFmt.wBitsPerSample & 0x1) ? WAVE_FORMAT_WMAUDIO3 : WAVE_FORMAT_WMAUDIO2; + pFormat->cbSize = 0; + break; + + case MINIWAVEFORMAT::TAG_XMA: // XMA2 is supported by Xbox One +#if defined(_XBOX_ONE) && defined(_TITLE) + if ( maxsize < sizeof(XMA2WAVEFORMATEX) ) + return HRESULT_FROM_WIN32( ERROR_MORE_DATA ); + + pFormat->wFormatTag = WAVE_FORMAT_XMA2; + pFormat->cbSize = sizeof(XMA2WAVEFORMATEX) - sizeof(WAVEFORMATEX); + { + auto xmaFmt = reinterpret_cast(pFormat); + + xmaFmt->NumStreams = static_cast( (miniFmt.nChannels + 1) / 2 ); + xmaFmt->BytesPerBlock = 65536 /* XACT_FIXED_XMA_BLOCK_SIZE */; + xmaFmt->EncoderVersion = 4 /* XMAENCODER_VERSION_XMA2 */; + + auto seekTable = FindSeekTable( index, m_seekData.get(), m_header, m_data ); + if ( seekTable ) + { + xmaFmt->BlockCount = static_cast( *seekTable ); + } + else + { + xmaFmt->BlockCount = 0; + } + + switch( miniFmt.nChannels ) + { + case 1: xmaFmt->ChannelMask = SPEAKER_MONO; break; + case 2: xmaFmt->ChannelMask = SPEAKER_STEREO; break; + case 3: xmaFmt->ChannelMask = SPEAKER_2POINT1; break; + case 4: xmaFmt->ChannelMask = SPEAKER_QUAD; break; + case 5: xmaFmt->ChannelMask = SPEAKER_4POINT1; break; + case 6: xmaFmt->ChannelMask = SPEAKER_5POINT1; break; + case 7: xmaFmt->ChannelMask = SPEAKER_5POINT1 | SPEAKER_BACK_CENTER; break; + case 8: xmaFmt->ChannelMask = SPEAKER_7POINT1; break; + default: xmaFmt->ChannelMask = DWORD(-1); break; + } + + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + DWORD dwOffset, dwLength; + entry.ComputeLocations( dwOffset, dwLength, index, m_header, m_data, reinterpret_cast( m_entries.get() ) ); + + xmaFmt->SamplesEncoded = entry.GetDuration( dwLength, m_data, seekTable ); + + xmaFmt->PlayBegin = xmaFmt->PlayLength = + xmaFmt->LoopBegin = xmaFmt->LoopLength = xmaFmt->LoopCount = 0; + } + else + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + xmaFmt->SamplesEncoded = entry.Duration; + xmaFmt->PlayBegin = 0; + xmaFmt->PlayLength = entry.PlayRegion.dwLength; + + if ( entry.LoopRegion.dwTotalSamples > 0 ) + { + xmaFmt->LoopBegin = entry.LoopRegion.dwStartSample; + xmaFmt->LoopLength = entry.LoopRegion.dwTotalSamples; + xmaFmt->LoopCount = 0xff /* XACTLOOPCOUNT_INFINITE */; + } + else + { + xmaFmt->LoopBegin = xmaFmt->LoopLength = xmaFmt->LoopCount = 0; + } + } + } + break; +#else + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); +#endif + + default: + return E_FAIL; + } + + pFormat->nChannels = miniFmt.nChannels; + pFormat->wBitsPerSample = miniFmt.BitsPerSample(); + pFormat->nBlockAlign = (WORD) miniFmt.BlockAlign(); + pFormat->nSamplesPerSec = miniFmt.nSamplesPerSec; + pFormat->nAvgBytesPerSec = miniFmt.AvgBytesPerSec(); + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Impl::GetWaveData( uint32_t index, const uint8_t** pData, uint32_t& dataSize ) const +{ + if ( !pData ) + return E_INVALIDARG; + + if ( index >= m_data.dwEntryCount || !m_entries ) + { + return E_FAIL; + } + +#if defined(_XBOX_ONE) && defined(_TITLE) + const uint8_t* waveData = ( m_xmaMemory ) ? reinterpret_cast( m_xmaMemory ) : m_waveData.get(); +#else + const uint8_t* waveData = m_waveData.get(); +#endif + + if ( !waveData ) + return E_FAIL; + + if ( m_data.dwFlags & BANKDATA::TYPE_STREAMING ) + { + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + if ( !m_prepared ) + { + return HRESULT_FROM_WIN32( ERROR_IO_INCOMPLETE ); + } + + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + DWORD dwOffset, dwLength; + entry.ComputeLocations( dwOffset, dwLength, index, m_header, m_data, reinterpret_cast( m_entries.get() ) ); + + if ( ( dwOffset + dwLength ) > m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + *pData = &waveData[ dwOffset ]; + dataSize = dwLength; + } + else + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + if ( ( entry.PlayRegion.dwOffset + entry.PlayRegion.dwLength ) > m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength ) + { + return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); + } + + *pData = &waveData[ entry.PlayRegion.dwOffset ]; + dataSize = entry.PlayRegion.dwLength; + } + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Impl::GetSeekTable( uint32_t index, const uint32_t** pData, uint32_t& dataCount, uint32_t& tag ) const +{ + if ( !pData ) + return E_INVALIDARG; + + *pData = nullptr; + dataCount = 0; + tag = 0; + + if ( index >= m_data.dwEntryCount || !m_entries ) + { + return E_FAIL; + } + + if ( !m_seekData ) + return S_OK; + + auto& miniFmt = ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) ? m_data.CompactFormat : ( reinterpret_cast( m_entries.get() )[ index ].Format ); + + switch( miniFmt.wFormatTag ) + { + case MINIWAVEFORMAT::TAG_WMA: + tag = (miniFmt.wBitsPerSample & 0x1) ? WAVE_FORMAT_WMAUDIO3 : WAVE_FORMAT_WMAUDIO2; + break; + + case MINIWAVEFORMAT::TAG_XMA: + tag = 0x166 /* WAVE_FORMAT_XMA2 */; + break; + + default: + return S_OK; + } + + auto seekTable = FindSeekTable( index, m_seekData.get(), m_header, m_data ); + if ( !seekTable ) + return S_OK; + + dataCount = *seekTable; + *pData = seekTable + 1; + + return S_OK; +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Impl::GetMetadata( uint32_t index, Metadata& metadata ) const +{ + if ( index >= m_data.dwEntryCount || !m_entries ) + { + return E_FAIL; + } + + if ( m_data.dwFlags & BANKDATA::FLAGS_COMPACT ) + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + DWORD dwOffset, dwLength; + entry.ComputeLocations( dwOffset, dwLength, index, m_header, m_data, reinterpret_cast( m_entries.get() ) ); + + auto seekTable = FindSeekTable( index, m_seekData.get(), m_header, m_data ); + metadata.duration = entry.GetDuration( dwLength, m_data, seekTable ); + metadata.loopStart = metadata.loopLength = 0; + metadata.offsetBytes = dwOffset; + metadata.lengthBytes = dwLength; + } + else + { + auto& entry = reinterpret_cast( m_entries.get() )[ index ]; + + metadata.duration = entry.Duration; + metadata.loopStart = entry.LoopRegion.dwStartSample; + metadata.loopLength = entry.LoopRegion.dwTotalSamples; + metadata.offsetBytes = entry.PlayRegion.dwOffset; + metadata.lengthBytes = entry.PlayRegion.dwLength; + } + + return S_OK; +} + + +bool WaveBankReader::Impl::UpdatePrepared() +{ + if ( m_prepared ) + return true; + + if ( m_async == INVALID_HANDLE_VALUE ) + return false; + + if ( m_request.hEvent != 0 ) + { + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + DWORD bytes; + BOOL result = GetOverlappedResultEx( m_async, &m_request, &bytes, 0, FALSE ); +#else + bool result = HasOverlappedIoCompleted( &m_request ); +#endif + if ( result ) + { + m_prepared = true; + + memset( &m_request, 0, sizeof(OVERLAPPED) ); + } + } + + return m_prepared; +} + + + +//-------------------------------------------------------------------------------------- +WaveBankReader::WaveBankReader() : + pImpl( new Impl ) +{ +} + + +WaveBankReader::~WaveBankReader() +{ +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::Open( const wchar_t* szFileName ) +{ + return pImpl->Open( szFileName ); +} + + +_Use_decl_annotations_ +uint32_t WaveBankReader::Find( const char* name ) const +{ + auto it = pImpl->m_names.find( name ); + if ( it != pImpl->m_names.cend() ) + { + return it->second; + } + + return uint32_t(-1); +} + + +bool WaveBankReader::IsPrepared() +{ + if ( pImpl->m_prepared ) + return true; + + return pImpl->UpdatePrepared(); +} + + +void WaveBankReader::WaitOnPrepare() +{ + if ( pImpl->m_prepared ) + return; + + if ( pImpl->m_request.hEvent != 0 ) + { + WaitForSingleObjectEx( pImpl->m_request.hEvent, INFINITE, FALSE ); + + pImpl->UpdatePrepared(); + } +} + + +bool WaveBankReader::HasNames() const +{ + return !pImpl->m_names.empty(); +} + + +bool WaveBankReader::IsStreamingBank() const +{ + return (pImpl->m_data.dwFlags & BANKDATA::TYPE_STREAMING) != 0; +} + + +#if defined(_XBOX_ONE) && defined(_TITLE) +bool WaveBankReader::HasXMA() const +{ + return (pImpl->m_xmaMemory != 0); +} +#endif + + +const char* WaveBankReader::BankName() const +{ + return pImpl->m_data.szBankName; +} + + +uint32_t WaveBankReader::Count() const +{ + return pImpl->m_data.dwEntryCount; +} + + +uint32_t WaveBankReader::BankAudioSize() const +{ + return pImpl->m_header.Segments[HEADER::SEGIDX_ENTRYWAVEDATA].dwLength; +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::GetFormat( uint32_t index, WAVEFORMATEX* pFormat, size_t maxsize ) const +{ + return pImpl->GetFormat( index, pFormat, maxsize ); +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::GetWaveData( uint32_t index, const uint8_t** pData, uint32_t& dataSize ) const +{ + return pImpl->GetWaveData( index, pData, dataSize ); +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::GetSeekTable( uint32_t index, const uint32_t** pData, uint32_t& dataCount, uint32_t& tag ) const +{ + return pImpl->GetSeekTable( index, pData, dataCount, tag ); +} + + +_Use_decl_annotations_ +HRESULT WaveBankReader::GetMetadata( uint32_t index, Metadata& metadata ) const +{ + return pImpl->GetMetadata( index, metadata ); +} + + +HANDLE WaveBankReader::GetAsyncHandle() const +{ + return ( pImpl->m_data.dwFlags & BANKDATA::TYPE_STREAMING ) ? pImpl->m_async : INVALID_HANDLE_VALUE; +} diff --git a/Kits/DirectXTK12/Audio/WaveBankReader.h b/Kits/DirectXTK12/Audio/WaveBankReader.h new file mode 100644 index 00000000..3b743e31 --- /dev/null +++ b/Kits/DirectXTK12/Audio/WaveBankReader.h @@ -0,0 +1,80 @@ +//-------------------------------------------------------------------------------------- +// File: WaveBankReader.h +// +// Functions for loading audio data from Wave Banks +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include + + +namespace DirectX +{ + class WaveBankReader + { + public: + WaveBankReader(); + + WaveBankReader(WaveBankReader const&) = delete; + WaveBankReader& operator= (WaveBankReader const&) = delete; + + ~WaveBankReader(); + + HRESULT Open( _In_z_ const wchar_t* szFileName ); + + uint32_t Find( _In_z_ const char* name ) const; + + bool IsPrepared(); + void WaitOnPrepare(); + + bool HasNames() const; + bool IsStreamingBank() const; + +#if defined(_XBOX_ONE) && defined(_TITLE) + bool HasXMA() const; +#endif + + const char* BankName() const; + + uint32_t Count() const; + + uint32_t BankAudioSize() const; + + HRESULT GetFormat( _In_ uint32_t index, _Out_writes_bytes_(maxsize) WAVEFORMATEX* pFormat, _In_ size_t maxsize ) const; + + HRESULT GetWaveData( _In_ uint32_t index, _Outptr_ const uint8_t** pData, _Out_ uint32_t& dataSize ) const; + + HRESULT GetSeekTable( _In_ uint32_t index, _Out_ const uint32_t** pData, _Out_ uint32_t& dataCount, _Out_ uint32_t& tag ) const; + + HANDLE GetAsyncHandle() const; + + struct Metadata + { + uint32_t duration; + uint32_t loopStart; + uint32_t loopLength; + uint32_t offsetBytes; + uint32_t lengthBytes; + }; + HRESULT GetMetadata( _In_ uint32_t index, _Out_ Metadata& metadata ) const; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj new file mode 100644 index 00000000..a8ec8b0a --- /dev/null +++ b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj @@ -0,0 +1,454 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + + + Document + + + + + + + {945B8F0E-AE5F-447C-933A-9D069532D3E4} + StaticLibrary + DirectXTK12 + DirectXTK12 + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + + + + StaticLibrary + true + v140 + + + StaticLibrary + true + v140 + + + StaticLibrary + true + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + Bin\Windows10\$(Platform)\$(Configuration)\ + Bin\Windows10\$(Platform)\$(Configuration)\ + DirectXTK12 + false + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + StreamingSIMDExtensions2 + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + StreamingSIMDExtensions2 + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + Use + true + true + $(ProjectDir)Inc;$(ProjectDir)Src;%(AdditionalIncludeDirectories) + Fast + $(IntDir)$(TargetName).pdb + Level4 + _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS;%(PreprocessorDefinitions) + + + Console + false + false + + + /IGNORE:4264 %(AdditionalOptions) + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj.filters b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj.filters new file mode 100644 index 00000000..b03f0f12 --- /dev/null +++ b/Kits/DirectXTK12/DirectXTK_Windows10.vcxproj.filters @@ -0,0 +1,521 @@ + + + + + {a77af43b-f2ab-4dcc-b84e-70909b198d8a} + + + {4a81ebd8-dd1a-46fb-ad14-8b57d8e92774} + + + {a872f54e-e97f-4e14-a946-da034ce61f99} + + + {e536bb5b-5908-4d5a-b629-6a73cf2fc9ca} + + + {fe608244-a8ad-4cca-b766-e82f3d32405b} + + + {cdc2c333-afc0-4a50-af16-b00d55d5eae9} + + + {6a91517d-6346-497f-a53c-72b517d1555b} + + + {748d343b-b201-4335-958e-d5457382f87b} + + + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Inc + + + Src + + + Src + + + Audio + + + Audio + + + Audio + + + Audio + + + Inc + + + Inc + + + Inc + + + Src + + + Src + + + Src + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Inc\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Inc + + + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders\Compiled + + + Src\Shaders + + + Inc\Shared + + + Src\Shared + + + Src\Shaders + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + Src\Shaders\Shared + + + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Audio + + + Src + + + Src + + + Src + + + Src + + + Src + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src\Shared + + + Src + + + + + + \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/Audio.h b/Kits/DirectXTK12/Inc/Audio.h new file mode 100644 index 00000000..ce0179e7 --- /dev/null +++ b/Kits/DirectXTK12/Inc/Audio.h @@ -0,0 +1,682 @@ +//-------------------------------------------------------------------------------------- +// File: Audio.h +// +// DirectXTK for Audio header +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#pragma comment(lib,"acphal.lib") +#endif + +#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP +#pragma comment(lib,"PhoneAudioSes.lib") +#endif + +#ifndef XAUDIO2_HELPER_FUNCTIONS +#define XAUDIO2_HELPER_FUNCTIONS +#endif + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) +#if defined(_MSC_VER) && (_MSC_VER < 1700) +#error DirectX Tool Kit for Audio does not support VS 2010 without the DirectX SDK +#endif +#include +#include +#include +#include +#pragma comment(lib,"xaudio2.lib") +#else +// Using XAudio 2.7 requires the DirectX SDK +#include +#include +#include +#include +#pragma warning(push) +#pragma warning( disable : 4005 ) +#include +#pragma warning(pop) +#pragma comment(lib,"x3daudio.lib") +#pragma comment(lib,"xapofx.lib") +#endif + +#include + +#include +#include +#include +#include +#include + +namespace DirectX +{ + class SoundEffectInstance; + + //---------------------------------------------------------------------------------- + struct AudioStatistics + { + size_t playingOneShots; // Number of one-shot sounds currently playing + size_t playingInstances; // Number of sound effect instances currently playing + size_t allocatedInstances; // Number of SoundEffectInstance allocated + size_t allocatedVoices; // Number of XAudio2 voices allocated (standard, 3D, one-shots, and idle one-shots) + size_t allocatedVoices3d; // Number of XAudio2 voices allocated for 3D + size_t allocatedVoicesOneShot; // Number of XAudio2 voices allocated for one-shot sounds + size_t allocatedVoicesIdle; // Number of XAudio2 voices allocated for one-shot sounds but not currently in use + size_t audioBytes; // Total wave data (in bytes) in SoundEffects and in-memory WaveBanks +#if defined(_XBOX_ONE) && defined(_TITLE) + size_t xmaAudioBytes; // Total wave data (in bytes) in SoundEffects and in-memory WaveBanks allocated with ApuAlloc +#endif + }; + + + //---------------------------------------------------------------------------------- + class IVoiceNotify + { + public: + virtual void __cdecl OnBufferEnd() = 0; + // Notfication that a voice buffer has finished + // Note this is called from XAudio2's worker thread, so it should perform very minimal and thread-safe operations + + virtual void __cdecl OnCriticalError() = 0; + // Notification that the audio engine encountered a critical error + + virtual void __cdecl OnReset() = 0; + // Notification of an audio engine reset + + virtual void __cdecl OnUpdate() = 0; + // Notification of an audio engine per-frame update (opt-in) + + virtual void __cdecl OnDestroyEngine() = 0; + // Notification that the audio engine is being destroyed + + virtual void __cdecl OnTrim() = 0; + // Notification of a request to trim the voice pool + + virtual void __cdecl GatherStatistics( AudioStatistics& stats ) const = 0; + // Contribute to statistics request + }; + + //---------------------------------------------------------------------------------- + enum AUDIO_ENGINE_FLAGS + { + AudioEngine_Default = 0x0, + + AudioEngine_EnvironmentalReverb = 0x1, + AudioEngine_ReverbUseFilters = 0x2, + AudioEngine_UseMasteringLimiter = 0x4, + + AudioEngine_Debug = 0x10000, + AudioEngine_ThrowOnNoAudioHW = 0x20000, + AudioEngine_DisableVoiceReuse = 0x40000, + }; + + inline AUDIO_ENGINE_FLAGS operator|(AUDIO_ENGINE_FLAGS a, AUDIO_ENGINE_FLAGS b) { return static_cast( static_cast(a) | static_cast(b) ); } + + enum SOUND_EFFECT_INSTANCE_FLAGS + { + SoundEffectInstance_Default = 0x0, + + SoundEffectInstance_Use3D = 0x1, + SoundEffectInstance_ReverbUseFilters = 0x2, + SoundEffectInstance_NoSetPitch = 0x4, + + SoundEffectInstance_UseRedirectLFE = 0x10000, + }; + + inline SOUND_EFFECT_INSTANCE_FLAGS operator|(SOUND_EFFECT_INSTANCE_FLAGS a, SOUND_EFFECT_INSTANCE_FLAGS b) { return static_cast( static_cast(a) | static_cast(b) ); } + + enum AUDIO_ENGINE_REVERB + { + Reverb_Off, + Reverb_Default, + Reverb_Generic, + Reverb_Forest, + Reverb_PaddedCell, + Reverb_Room, + Reverb_Bathroom, + Reverb_LivingRoom, + Reverb_StoneRoom, + Reverb_Auditorium, + Reverb_ConcertHall, + Reverb_Cave, + Reverb_Arena, + Reverb_Hangar, + Reverb_CarpetedHallway, + Reverb_Hallway, + Reverb_StoneCorridor, + Reverb_Alley, + Reverb_City, + Reverb_Mountains, + Reverb_Quarry, + Reverb_Plain, + Reverb_ParkingLot, + Reverb_SewerPipe, + Reverb_Underwater, + Reverb_SmallRoom, + Reverb_MediumRoom, + Reverb_LargeRoom, + Reverb_MediumHall, + Reverb_LargeHall, + Reverb_Plate, + Reverb_MAX + }; + + enum SoundState + { + STOPPED = 0, + PLAYING, + PAUSED + }; + + + //---------------------------------------------------------------------------------- + class AudioEngine + { + public: + explicit AudioEngine( AUDIO_ENGINE_FLAGS flags = AudioEngine_Default, _In_opt_ const WAVEFORMATEX* wfx = nullptr, _In_opt_z_ const wchar_t* deviceId = nullptr, + AUDIO_STREAM_CATEGORY category = AudioCategory_GameEffects ); + + AudioEngine(AudioEngine&& moveFrom); + AudioEngine& operator= (AudioEngine&& moveFrom); + + AudioEngine(AudioEngine const&) = delete; + AudioEngine& operator= (AudioEngine const&) = delete; + + virtual ~AudioEngine(); + + bool __cdecl Update(); + // Performs per-frame processing for the audio engine, returns false if in 'silent mode' + + bool __cdecl Reset( _In_opt_ const WAVEFORMATEX* wfx = nullptr, _In_opt_z_ const wchar_t* deviceId = nullptr ); + // Reset audio engine from critical error/silent mode using a new device; can also 'migrate' the graph + // Returns true if succesfully reset, false if in 'silent mode' due to no default device + // Note: One shots are lost, all SoundEffectInstances are in the STOPPED state after successful reset + + void __cdecl Suspend(); + void __cdecl Resume(); + // Suspend/resumes audio processing (i.e. global pause/resume) + + float __cdecl GetMasterVolume() const; + void __cdecl SetMasterVolume( float volume ); + // Master volume property for all sounds + + void __cdecl SetReverb( AUDIO_ENGINE_REVERB reverb ); + void __cdecl SetReverb( _In_opt_ const XAUDIO2FX_REVERB_PARAMETERS* native ); + // Sets environmental reverb for 3D positional audio (if active) + + void __cdecl SetMasteringLimit( int release, int loudness ); + // Sets the mastering volume limiter properties (if active) + + AudioStatistics __cdecl GetStatistics() const; + // Gathers audio engine statistics + + WAVEFORMATEXTENSIBLE __cdecl GetOutputFormat() const; + // Returns the format consumed by the mastering voice (which is the same as the device output if defaults are used) + + uint32_t __cdecl GetChannelMask() const; + // Returns the output channel mask + + int __cdecl GetOutputChannels() const; + // Returns the number of output channels + + bool __cdecl IsAudioDevicePresent() const; + // Returns true if the audio graph is operating normally, false if in 'silent mode' + + bool __cdecl IsCriticalError() const; + // Returns true if the audio graph is halted due to a critical error (which also places the engine into 'silent mode') + + // Voice pool management. + void __cdecl SetDefaultSampleRate( int sampleRate ); + // Sample rate for voices in the reuse pool (defaults to 44100) + + void __cdecl SetMaxVoicePool( size_t maxOneShots, size_t maxInstances ); + // Maximum number of voices to allocate for one-shots and instances + // Note: one-shots over this limit are ignored; too many instance voices throws an exception + + void __cdecl TrimVoicePool(); + // Releases any currently unused voices + + // Internal-use functions + void __cdecl AllocateVoice( _In_ const WAVEFORMATEX* wfx, SOUND_EFFECT_INSTANCE_FLAGS flags, bool oneshot, _Outptr_result_maybenull_ IXAudio2SourceVoice** voice ); + + void __cdecl DestroyVoice( _In_ IXAudio2SourceVoice* voice ); + // Should only be called for instance voices, not one-shots + + void __cdecl RegisterNotify( _In_ IVoiceNotify* notify, bool usesUpdate ); + void __cdecl UnregisterNotify( _In_ IVoiceNotify* notify, bool usesOneShots, bool usesUpdate ); + + // XAudio2 interface access + IXAudio2* __cdecl GetInterface() const; + IXAudio2MasteringVoice* __cdecl GetMasterVoice() const; + IXAudio2SubmixVoice* __cdecl GetReverbVoice() const; + X3DAUDIO_HANDLE& __cdecl Get3DHandle() const; + + // Static functions + struct RendererDetail + { + std::wstring deviceId; + std::wstring description; + }; + + static std::vector __cdecl GetRendererDetails(); + // Returns a list of valid audio endpoint devices + + private: + // Private implementation. + class Impl; + std::unique_ptr pImpl; + }; + + + //---------------------------------------------------------------------------------- + class WaveBank + { + public: + WaveBank( _In_ AudioEngine* engine, _In_z_ const wchar_t* wbFileName ); + + WaveBank(WaveBank&& moveFrom); + WaveBank& operator= (WaveBank&& moveFrom); + + WaveBank(WaveBank const&) = delete; + WaveBank& operator= (WaveBank const&) = delete; + + virtual ~WaveBank(); + + void __cdecl Play( int index ); + void __cdecl Play( int index, float volume, float pitch, float pan ); + + void __cdecl Play( _In_z_ const char* name ); + void __cdecl Play( _In_z_ const char* name, float volume, float pitch, float pan ); + + std::unique_ptr __cdecl CreateInstance( int index, SOUND_EFFECT_INSTANCE_FLAGS flags = SoundEffectInstance_Default ); + std::unique_ptr __cdecl CreateInstance( _In_z_ const char* name, SOUND_EFFECT_INSTANCE_FLAGS flags = SoundEffectInstance_Default ); + + bool __cdecl IsPrepared() const; + bool __cdecl IsInUse() const; + bool __cdecl IsStreamingBank() const; + + size_t __cdecl GetSampleSizeInBytes( int index ) const; + // Returns size of wave audio data + + size_t __cdecl GetSampleDuration( int index ) const; + // Returns the duration in samples + + size_t __cdecl GetSampleDurationMS( int index ) const; + // Returns the duration in milliseconds + + const WAVEFORMATEX* __cdecl GetFormat( int index, _Out_writes_bytes_(maxsize) WAVEFORMATEX* wfx, size_t maxsize ) const; + + int __cdecl Find( _In_z_ const char* name ) const; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/ ) + bool __cdecl FillSubmitBuffer( int index, _Out_ XAUDIO2_BUFFER& buffer, _Out_ XAUDIO2_BUFFER_WMA& wmaBuffer ) const; +#else + void __cdecl FillSubmitBuffer( int index, _Out_ XAUDIO2_BUFFER& buffer ) const; +#endif + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + // Private interface + void __cdecl UnregisterInstance( _In_ SoundEffectInstance* instance ); + + friend class SoundEffectInstance; + }; + + + //---------------------------------------------------------------------------------- + class SoundEffect + { + public: + SoundEffect( _In_ AudioEngine* engine, _In_z_ const wchar_t* waveFileName ); + + SoundEffect( _In_ AudioEngine* engine, _Inout_ std::unique_ptr& wavData, + _In_ const WAVEFORMATEX* wfx, _In_reads_bytes_(audioBytes) const uint8_t* startAudio, size_t audioBytes ); + + SoundEffect( _In_ AudioEngine* engine, _Inout_ std::unique_ptr& wavData, + _In_ const WAVEFORMATEX* wfx, _In_reads_bytes_(audioBytes) const uint8_t* startAudio, size_t audioBytes, + uint32_t loopStart, uint32_t loopLength ); + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/) + + SoundEffect( _In_ AudioEngine* engine, _Inout_ std::unique_ptr& wavData, + _In_ const WAVEFORMATEX* wfx, _In_reads_bytes_(audioBytes) const uint8_t* startAudio, size_t audioBytes, + _In_reads_(seekCount) const uint32_t* seekTable, size_t seekCount ); + +#endif + + SoundEffect(SoundEffect&& moveFrom); + SoundEffect& operator= (SoundEffect&& moveFrom); + + SoundEffect(SoundEffect const&) = delete; + SoundEffect& operator= (SoundEffect const&) = delete; + + virtual ~SoundEffect(); + + void __cdecl Play(); + void __cdecl Play(float volume, float pitch, float pan); + + std::unique_ptr __cdecl CreateInstance( SOUND_EFFECT_INSTANCE_FLAGS flags = SoundEffectInstance_Default ); + + bool __cdecl IsInUse() const; + + size_t __cdecl GetSampleSizeInBytes() const; + // Returns size of wave audio data + + size_t __cdecl GetSampleDuration() const; + // Returns the duration in samples + + size_t __cdecl GetSampleDurationMS() const; + // Returns the duration in milliseconds + + const WAVEFORMATEX* __cdecl GetFormat() const; + +#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/) + bool __cdecl FillSubmitBuffer( _Out_ XAUDIO2_BUFFER& buffer, _Out_ XAUDIO2_BUFFER_WMA& wmaBuffer ) const; +#else + void __cdecl FillSubmitBuffer( _Out_ XAUDIO2_BUFFER& buffer ) const; +#endif + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + // Private interface + void __cdecl UnregisterInstance( _In_ SoundEffectInstance* instance ); + + friend class SoundEffectInstance; + }; + + + //---------------------------------------------------------------------------------- + struct AudioListener : public X3DAUDIO_LISTENER + { + AudioListener() + { + memset( this, 0, sizeof(X3DAUDIO_LISTENER) ); + + OrientFront.z = -1.f; + + OrientTop.y = 1.f; + } + + void XM_CALLCONV SetPosition( FXMVECTOR v ) + { + XMStoreFloat3( reinterpret_cast( &Position ), v ); + } + void __cdecl SetPosition( const XMFLOAT3& pos ) + { + Position.x = pos.x; + Position.y = pos.y; + Position.z = pos.z; + } + + void XM_CALLCONV SetVelocity( FXMVECTOR v ) + { + XMStoreFloat3( reinterpret_cast( &Velocity ), v ); + } + void __cdecl SetVelocity( const XMFLOAT3& vel ) + { + Velocity.x = vel.x; + Velocity.y = vel.y; + Velocity.z = vel.z; + } + + void XM_CALLCONV SetOrientation( FXMVECTOR forward, FXMVECTOR up ) + { + XMStoreFloat3( reinterpret_cast( &OrientFront ), forward ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), up ); + } + void __cdecl SetOrientation( const XMFLOAT3& forward, const XMFLOAT3& up ) + { + OrientFront.x = forward.x; OrientTop.x = up.x; + OrientFront.y = forward.y; OrientTop.y = up.y; + OrientFront.z = forward.z; OrientTop.z = up.z; + } + + void XM_CALLCONV SetOrientationFromQuaternion( FXMVECTOR quat ) + { + XMVECTOR forward = XMVector3Rotate( g_XMIdentityR2, quat ); + XMStoreFloat3( reinterpret_cast( &OrientFront ), forward ); + + XMVECTOR up = XMVector3Rotate( g_XMIdentityR1, quat ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), up ); + } + + void XM_CALLCONV Update( FXMVECTOR newPos, XMVECTOR upDir, float dt ) + // Updates velocity and orientation by tracking changes in position over time... + { + if ( dt > 0.f ) + { + XMVECTOR lastPos = XMLoadFloat3( reinterpret_cast( &Position ) ); + + XMVECTOR vDelta = ( newPos - lastPos ); + XMVECTOR v = vDelta / dt; + XMStoreFloat3( reinterpret_cast( &Velocity ), v ); + + vDelta = XMVector3Normalize( vDelta ); + XMStoreFloat3( reinterpret_cast( &OrientFront ), vDelta ); + + v = XMVector3Cross( upDir, vDelta ); + v = XMVector3Normalize( v ); + + v = XMVector3Cross( vDelta, v ); + v = XMVector3Normalize( v ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), v ); + + XMStoreFloat3( reinterpret_cast( &Position ), newPos ); + } + } + }; + + + //---------------------------------------------------------------------------------- + struct AudioEmitter : public X3DAUDIO_EMITTER + { + float EmitterAzimuths[XAUDIO2_MAX_AUDIO_CHANNELS]; + + AudioEmitter() + { + memset( this, 0, sizeof(X3DAUDIO_EMITTER) ); + memset( EmitterAzimuths, 0, sizeof(EmitterAzimuths) ); + + OrientFront.z = -1.f; + + OrientTop.y = + ChannelRadius = + CurveDistanceScaler = + DopplerScaler = 1.f; + + ChannelCount = 1; + pChannelAzimuths = EmitterAzimuths; + + InnerRadiusAngle = X3DAUDIO_PI / 4.0f; + } + + void XM_CALLCONV SetPosition( FXMVECTOR v ) + { + XMStoreFloat3( reinterpret_cast( &Position ), v ); + } + void __cdecl SetPosition( const XMFLOAT3& pos ) + { + Position.x = pos.x; + Position.y = pos.y; + Position.z = pos.z; + } + + void XM_CALLCONV SetVelocity( FXMVECTOR v ) + { + XMStoreFloat3( reinterpret_cast( &Velocity ), v ); + } + void __cdecl SetVelocity( const XMFLOAT3& vel ) + { + Velocity.x = vel.x; + Velocity.y = vel.y; + Velocity.z = vel.z; + } + + void XM_CALLCONV SetOrientation( FXMVECTOR forward, FXMVECTOR up ) + { + XMStoreFloat3( reinterpret_cast( &OrientFront ), forward ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), up ); + } + void __cdecl SetOrientation( const XMFLOAT3& forward, const XMFLOAT3& up ) + { + OrientFront.x = forward.x; OrientTop.x = up.x; + OrientFront.y = forward.y; OrientTop.y = up.y; + OrientFront.z = forward.z; OrientTop.z = up.z; + } + + void XM_CALLCONV SetOrientationFromQuaternion( FXMVECTOR quat ) + { + XMVECTOR forward = XMVector3Rotate( g_XMIdentityR2, quat ); + XMStoreFloat3( reinterpret_cast( &OrientFront ), forward ); + + XMVECTOR up = XMVector3Rotate( g_XMIdentityR1, quat ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), up ); + } + + void XM_CALLCONV Update( FXMVECTOR newPos, XMVECTOR upDir, float dt ) + // Updates velocity and orientation by tracking changes in position over time... + { + if ( dt > 0.f ) + { + XMVECTOR lastPos = XMLoadFloat3( reinterpret_cast( &Position ) ); + + XMVECTOR vDelta = ( newPos - lastPos ); + XMVECTOR v = vDelta / dt; + XMStoreFloat3( reinterpret_cast( &Velocity ), v ); + + vDelta = XMVector3Normalize( vDelta ); + XMStoreFloat3( reinterpret_cast( &OrientFront ), vDelta ); + + v = XMVector3Cross( upDir, vDelta ); + v = XMVector3Normalize( v ); + + v = XMVector3Cross( vDelta, v ); + v = XMVector3Normalize( v ); + XMStoreFloat3( reinterpret_cast( &OrientTop ), v ); + + XMStoreFloat3( reinterpret_cast( &Position ), newPos ); + } + } + }; + + + //---------------------------------------------------------------------------------- + class SoundEffectInstance + { + public: + SoundEffectInstance(SoundEffectInstance&& moveFrom); + SoundEffectInstance& operator= (SoundEffectInstance&& moveFrom); + + SoundEffectInstance(SoundEffectInstance const&) = delete; + SoundEffectInstance& operator= (SoundEffectInstance const&) = delete; + + virtual ~SoundEffectInstance(); + + void __cdecl Play( bool loop = false ); + void __cdecl Stop( bool immediate = true ); + void __cdecl Pause(); + void __cdecl Resume(); + + void __cdecl SetVolume( float volume ); + void __cdecl SetPitch( float pitch ); + void __cdecl SetPan( float pan ); + + void __cdecl Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords = true ); + + bool __cdecl IsLooped() const; + + SoundState __cdecl GetState(); + + // Notifications. + void __cdecl OnDestroyParent(); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + // Private constructors + SoundEffectInstance( _In_ AudioEngine* engine, _In_ SoundEffect* effect, SOUND_EFFECT_INSTANCE_FLAGS flags ); + SoundEffectInstance( _In_ AudioEngine* engine, _In_ WaveBank* effect, int index, SOUND_EFFECT_INSTANCE_FLAGS flags ); + + friend std::unique_ptr __cdecl SoundEffect::CreateInstance( SOUND_EFFECT_INSTANCE_FLAGS ); + friend std::unique_ptr __cdecl WaveBank::CreateInstance( int, SOUND_EFFECT_INSTANCE_FLAGS ); + }; + + + //---------------------------------------------------------------------------------- + class DynamicSoundEffectInstance + { + public: + DynamicSoundEffectInstance( _In_ AudioEngine* engine, + _In_opt_ std::function bufferNeeded, + int sampleRate, int channels, int sampleBits = 16, + SOUND_EFFECT_INSTANCE_FLAGS flags = SoundEffectInstance_Default ); + DynamicSoundEffectInstance(DynamicSoundEffectInstance&& moveFrom); + DynamicSoundEffectInstance& operator= (DynamicSoundEffectInstance&& moveFrom); + + DynamicSoundEffectInstance(DynamicSoundEffectInstance const&) = delete; + DynamicSoundEffectInstance& operator= (DynamicSoundEffectInstance const&) = delete; + + virtual ~DynamicSoundEffectInstance(); + + void __cdecl Play(); + void __cdecl Stop( bool immediate = true ); + void __cdecl Pause(); + void __cdecl Resume(); + + void __cdecl SetVolume( float volume ); + void __cdecl SetPitch( float pitch ); + void __cdecl SetPan( float pan ); + + void __cdecl Apply3D( const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords = true ); + + void __cdecl SubmitBuffer( _In_reads_bytes_(audioBytes) const uint8_t* pAudioData, size_t audioBytes ); + void __cdecl SubmitBuffer( _In_reads_bytes_(audioBytes) const uint8_t* pAudioData, uint32_t offset, size_t audioBytes ); + + SoundState __cdecl GetState(); + + size_t __cdecl GetSampleDuration( size_t bytes ) const; + // Returns duration in samples of a buffer of a given size + + size_t __cdecl GetSampleDurationMS( size_t bytes ) const; + // Returns duration in milliseconds of a buffer of a given size + + size_t __cdecl GetSampleSizeInBytes( uint64_t duration ) const; + // Returns size of a buffer for a duration given in milliseconds + + int __cdecl GetPendingBufferCount() const; + + const WAVEFORMATEX* __cdecl GetFormat() const; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/CommonStates.h b/Kits/DirectXTK12/Inc/CommonStates.h new file mode 100644 index 00000000..9197c9c8 --- /dev/null +++ b/Kits/DirectXTK12/Inc/CommonStates.h @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------------------------- +// File: CommonStates.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + + +namespace DirectX +{ + class CommonStates + { + public: + CommonStates() = delete; + + // Blend states. + static const D3D12_BLEND_DESC Opaque; + static const D3D12_BLEND_DESC AlphaBlend; + static const D3D12_BLEND_DESC Additive; + static const D3D12_BLEND_DESC NonPremultiplied; + + // Depth stencil states. + static const D3D12_DEPTH_STENCIL_DESC DepthNone; + static const D3D12_DEPTH_STENCIL_DESC DepthDefault; + static const D3D12_DEPTH_STENCIL_DESC DepthRead; + + // Rasterizer states. + static const D3D12_RASTERIZER_DESC CullNone; + static const D3D12_RASTERIZER_DESC CullClockwise; + static const D3D12_RASTERIZER_DESC CullCounterClockwise; + static const D3D12_RASTERIZER_DESC Wireframe; + + // Sampler states. + static const D3D12_SAMPLER_DESC PointWrap; + static const D3D12_SAMPLER_DESC PointClamp; + static const D3D12_SAMPLER_DESC LinearWrap; + static const D3D12_SAMPLER_DESC LinearClamp; + static const D3D12_SAMPLER_DESC AnisotropicWrap; + static const D3D12_SAMPLER_DESC AnisotropicClamp; + }; +} diff --git a/Kits/DirectXTK12/Inc/DDSTextureLoader.h b/Kits/DirectXTK12/Inc/DDSTextureLoader.h new file mode 100644 index 00000000..86b7fa68 --- /dev/null +++ b/Kits/DirectXTK12/Inc/DDSTextureLoader.h @@ -0,0 +1,139 @@ +//-------------------------------------------------------------------------------------- +// File: DDSTextureLoader.h +// +// Functions for loading a DDS texture and creating a Direct3D runtime resource for it +// +// Note these functions are useful as a light-weight runtime loader for DDS files. For +// a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include + + +namespace DirectX +{ + class ResourceUploadBatch; + + enum DDS_ALPHA_MODE + { + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, + }; + + // Standard version + HRESULT __cdecl LoadDDSTextureFromMemory( + _In_ ID3D12Device* d3dDevice, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _Outptr_ ID3D12Resource** texture, + _Inout_ std::vector& subresources, + _In_ size_t maxsize = 0, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl LoadDDSTextureFromFile( + _In_ ID3D12Device* d3dDevice, + _In_z_ const wchar_t* szFileName, + _Outptr_ ID3D12Resource** texture, + _Inout_ std::unique_ptr& ddsData, + _Inout_ std::vector& subresources, + _In_ size_t maxsize = 0, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl CreateDDSTextureFromMemory( + _In_ ID3D12Device* device, + _In_ ResourceUploadBatch& resourceUpload, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _Outptr_ ID3D12Resource** texture, + _In_ bool generateMipsIfMissing = false, + _In_ size_t maxsize = 0, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl CreateDDSTextureFromFile( + _In_ ID3D12Device* device, + _In_ ResourceUploadBatch& resourceUpload, + _In_z_ const wchar_t* szFileName, + _Outptr_ ID3D12Resource** texture, + _In_ bool generateMipsIfMissing = false, + _In_ size_t maxsize = 0, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + // Extended version + HRESULT __cdecl LoadDDSTextureFromMemoryEx( + _In_ ID3D12Device* d3dDevice, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + _Inout_ std::vector& subresources, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl LoadDDSTextureFromFileEx( + _In_ ID3D12Device* d3dDevice, + _In_z_ const wchar_t* szFileName, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + _Inout_ std::unique_ptr& ddsData, + _Inout_ std::vector& subresources, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl CreateDDSTextureFromMemoryEx( + _In_ ID3D12Device* device, + _In_ ResourceUploadBatch& resourceUpload, + _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, + _In_ size_t ddsDataSize, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool generateMipsIfMissing, + _Outptr_ ID3D12Resource** texture, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); + + HRESULT __cdecl CreateDDSTextureFromFileEx( + _In_ ID3D12Device* device, + _In_ ResourceUploadBatch& resourceUpload, + _In_z_ const wchar_t* szFileName, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool generateMipsIfMissing, + _Outptr_ ID3D12Resource** texture, + _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr, + _Out_opt_ bool* isCubeMap = nullptr); +} diff --git a/Kits/DirectXTK12/Inc/DescriptorHeap.h b/Kits/DirectXTK12/Inc/DescriptorHeap.h new file mode 100644 index 00000000..ec3bc880 --- /dev/null +++ b/Kits/DirectXTK12/Inc/DescriptorHeap.h @@ -0,0 +1,126 @@ +//-------------------------------------------------------------------------------------- +// File: DescriptorHeap.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include + +#include + + +namespace DirectX +{ + // A contiguous linear random-access descriptor heap + class DescriptorHeap + { + public: + DescriptorHeap( + _In_ ID3D12DescriptorHeap* pExistingHeap); + DescriptorHeap( + _In_ ID3D12Device* device, + _In_ const D3D12_DESCRIPTOR_HEAP_DESC* pDesc); + DescriptorHeap( + _In_ ID3D12Device* device, + _In_ D3D12_DESCRIPTOR_HEAP_TYPE type, + _In_ D3D12_DESCRIPTOR_HEAP_FLAGS flags, + _In_ size_t count); + + DescriptorHeap(DescriptorHeap&&) = default; + DescriptorHeap& operator=(DescriptorHeap&&) = default; + + DescriptorHeap(const DescriptorHeap&) = delete; + DescriptorHeap& operator=(const DescriptorHeap&) = delete; + + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl WriteDescriptors( + _In_ ID3D12Device* device, + _In_ uint32_t offsetIntoHeap, + _In_ uint32_t totalDescriptorCount, + _In_reads_(descriptorRangeCount) const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts, + _In_reads_(descriptorRangeCount) const uint32_t* pDescriptorRangeSizes, + _In_ uint32_t descriptorRangeCount); + + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl WriteDescriptors( + _In_ ID3D12Device* device, + _In_ uint32_t offsetIntoHeap, + _In_reads_(descriptorRangeCount) const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts, + _In_reads_(descriptorRangeCount) const uint32_t* pDescriptorRangeSizes, + _In_ uint32_t descriptorRangeCount); + + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl WriteDescriptors( + _In_ ID3D12Device* device, + _In_ uint32_t offsetIntoHeap, + _In_reads_(descriptorCount) const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptors, + _In_ uint32_t descriptorCount); + + D3D12_GPU_DESCRIPTOR_HANDLE GetFirstGpuHandle() const + { + assert(m_desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + assert(m_pHeap != 0); + return m_hGPU; + } + + D3D12_CPU_DESCRIPTOR_HANDLE GetFirstCpuHandle() const + { + assert(m_pHeap != 0); + return m_hCPU; + } + + D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(_In_ size_t index) const + { + assert(m_pHeap != 0); + if (index >= m_desc.NumDescriptors) + { + throw std::out_of_range("CD3DX12_CPU_DESCRIPTOR_HANDLE"); + } + assert(m_desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_hGPU, static_cast(index), m_increment); + } + + D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(_In_ size_t index) const + { + assert(m_pHeap != 0); + if (index >= m_desc.NumDescriptors) + { + throw std::out_of_range("CD3DX12_CPU_DESCRIPTOR_HANDLE"); + } + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_hCPU, static_cast(index), m_increment); + } + + size_t Count() const { return m_desc.NumDescriptors; } + unsigned int Flags() const { return m_desc.Flags; } + D3D12_DESCRIPTOR_HEAP_TYPE Type() const { return m_desc.Type; } + size_t Increment() const { return m_increment; } + ID3D12DescriptorHeap* Heap() const { return m_pHeap.Get(); } + + static void __cdecl DefaultDesc( + _In_ D3D12_DESCRIPTOR_HEAP_TYPE type, + _Out_ D3D12_DESCRIPTOR_HEAP_DESC* pDesc); + + private: + void __cdecl Create(_In_ ID3D12Device* pDevice, _In_ const D3D12_DESCRIPTOR_HEAP_DESC* pDesc); + + Microsoft::WRL::ComPtr m_pHeap; + D3D12_DESCRIPTOR_HEAP_DESC m_desc; + CD3DX12_CPU_DESCRIPTOR_HANDLE m_hCPU; + CD3DX12_GPU_DESCRIPTOR_HANDLE m_hGPU; + uint32_t m_increment; + }; +} diff --git a/Kits/DirectXTK12/Inc/DirectXHelpers.h b/Kits/DirectXTK12/Inc/DirectXHelpers.h new file mode 100644 index 00000000..b8ec7526 --- /dev/null +++ b/Kits/DirectXTK12/Inc/DirectXHelpers.h @@ -0,0 +1,176 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXHelpers.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include + +#ifndef IID_GRAPHICS_PPV_ARGS +#define IID_GRAPHICS_PPV_ARGS(x) IID_PPV_ARGS(x) +#endif + +// +// The d3dx12.h header includes the following helper C++ classes and functions +// CD3DX12_RECT +// CD3DX12_BOX +// CD3DX12_DEPTH_STENCIL_DESC +// CD3DX12_BLEND_DESC +// CD3DX12_RASTERIZER_DESC +// CD3DX12_RESOURCE_ALLOCATION_INFO +// CD3DX12_HEAP_PROPERTIES +// CD3DX12_HEAP_DESC +// CD3DX12_CLEAR_VALUE +// CD3DX12_RANGE +// CD3DX12_SHADER_BYTECODE +// CD3DX12_TILED_RESOURCE_COORDINATE +// CD3DX12_TILE_REGION_SIZE +// CD3DX12_SUBRESOURCE_TILING +// CD3DX12_TILE_SHAPE +// CD3DX12_RESOURCE_BARRIER +// CD3DX12_PACKED_MIP_INFO +// CD3DX12_SUBRESOURCE_FOOTPRINT +// CD3DX12_TEXTURE_COPY_LOCATION +// CD3DX12_DESCRIPTOR_RANGE +// CD3DX12_ROOT_DESCRIPTOR_TABLE +// CD3DX12_ROOT_CONSTANTS +// CD3DX12_ROOT_DESCRIPTOR +// CD3DX12_ROOT_PARAMETER +// CD3DX12_STATIC_SAMPLER_DESC +// CD3DX12_ROOT_SIGNATURE_DESC +// CD3DX12_CPU_DESCRIPTOR_HANDLE +// CD3DX12_GPU_DESCRIPTOR_HANDLE +// CD3DX12_RESOURCE_DESC +// D3D12CalcSubresource +// D3D12DecomposeSubresource +// D3D12GetFormatPlaneCount +// MemcpySubresource +// GetRequiredIntermediateSize +// UpdateSubresources +// D3D12IsLayoutOpaque +// CommandListCast +// + + +namespace DirectX +{ + constexpr D3D12_CPU_DESCRIPTOR_HANDLE D3D12_CPU_DESCRIPTOR_HANDLE_ZERO = {}; + + // Creates a shader resource view from an arbitrary resource + void __cdecl CreateShaderResourceView( + _In_ ID3D12Device* d3dDevice, + _In_ ID3D12Resource* tex, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, + _In_ bool isCubeMap = false); + + // Shorthand for creating a root signature + inline HRESULT CreateRootSignature( + _In_ ID3D12Device* device, + _In_ const D3D12_ROOT_SIGNATURE_DESC* rootSignatureDesc, + _Out_ ID3D12RootSignature** rootSignature) + { + Microsoft::WRL::ComPtr pSignature; + Microsoft::WRL::ComPtr pError; + HRESULT hr = D3D12SerializeRootSignature(rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = device->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), + IID_GRAPHICS_PPV_ARGS(rootSignature) + ); + } + return hr; + } + + // Helper for obtaining texture size + inline XMUINT2 GetTextureSize(_In_ ID3D12Resource* tex) + { + auto desc = tex->GetDesc(); + return XMUINT2(static_cast(desc.Width), static_cast(desc.Height)); + } + + // Scoped PIX event. + class ScopedPixEvent + { + public: + ScopedPixEvent(_In_ ID3D12GraphicsCommandList* pCommandList, UINT64 /*metadata*/, PCWSTR pFormat) + : mCommandList(pCommandList) + { + PIXBeginEvent(pCommandList, 0, pFormat); + } + ~ScopedPixEvent() + { + PIXEndEvent(mCommandList); + } + + private: + ID3D12GraphicsCommandList* mCommandList; + }; + + // Helper sets a D3D resource name string (used by PIX and debug layer leak reporting). + template + inline void SetDebugObjectName(_In_ ID3D12DeviceChild* resource, _In_z_ const char(&name)[TNameLength]) + { + #if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + wchar_t wname[MAX_PATH]; + int result = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, TNameLength, wname, MAX_PATH); + if (result > 0) + { + resource->SetName(wname); + } + #else + UNREFERENCED_PARAMETER(resource); + UNREFERENCED_PARAMETER(name); + #endif + } + + template + inline void SetDebugObjectName(_In_ ID3D12DeviceChild* resource, _In_z_ const wchar_t(&name)[TNameLength]) + { + #if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + resource->SetName(name); + #else + UNREFERENCED_PARAMETER(resource); + UNREFERENCED_PARAMETER(name); + #endif + } + + // Helper for resource barrier. + inline void TransitionResource( + _In_ ID3D12GraphicsCommandList* commandList, + _In_ ID3D12Resource* resource, + _In_ D3D12_RESOURCE_STATES stateBefore, + _In_ D3D12_RESOURCE_STATES stateAfter) + { + assert(commandList != 0); + assert(resource != 0); + + if (stateBefore == stateAfter) + return; + + D3D12_RESOURCE_BARRIER desc = {}; + desc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + desc.Transition.pResource = resource; + desc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + desc.Transition.StateBefore = stateBefore; + desc.Transition.StateAfter = stateAfter; + + commandList->ResourceBarrier(1, &desc); + } +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/Effects.h b/Kits/DirectXTK12/Inc/Effects.h new file mode 100644 index 00000000..72e31ffe --- /dev/null +++ b/Kits/DirectXTK12/Inc/Effects.h @@ -0,0 +1,545 @@ +//-------------------------------------------------------------------------------------- +// File: Effects.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include "RenderTargetState.h" + +namespace DirectX +{ + class DescriptorHeap; + class ResourceUploadBatch; + + //---------------------------------------------------------------------------------- + // Abstract interface representing any effect which can be applied onto a D3D device context. + class IEffect + { + public: + virtual ~IEffect() { } + + virtual void __cdecl Apply( _In_ ID3D12GraphicsCommandList* deviceContext ) = 0; + }; + + + // Abstract interface for effects with world, view, and projection matrices. + class IEffectMatrices + { + public: + virtual ~IEffectMatrices() { } + + virtual void XM_CALLCONV SetWorld(FXMMATRIX value) = 0; + virtual void XM_CALLCONV SetView(FXMMATRIX value) = 0; + virtual void XM_CALLCONV SetProjection(FXMMATRIX value) = 0; + }; + + + // Abstract interface for effects which support directional lighting. + class IEffectLights + { + public: + virtual ~IEffectLights() { } + + virtual void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) = 0; + + virtual void __cdecl SetLightEnabled(int whichLight, bool value) = 0; + virtual void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) = 0; + virtual void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) = 0; + virtual void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) = 0; + + virtual void __cdecl EnableDefaultLighting() = 0; + + static const int MaxDirectionalLights = 3; + }; + + + // Abstract interface for effects which support fog. + class IEffectFog + { + public: + virtual ~IEffectFog() { } + + virtual void __cdecl SetFogStart(float value) = 0; + virtual void __cdecl SetFogEnd(float value) = 0; + virtual void XM_CALLCONV SetFogColor(FXMVECTOR value) = 0; + }; + + + // Abstract interface for effects which support skinning + class IEffectSkinning + { + public: + virtual ~IEffectSkinning() { } + + virtual void __cdecl SetWeightsPerVertex(int value) = 0; + virtual void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) = 0; + virtual void __cdecl ResetBoneTransforms() = 0; + + static const int MaxBones = 72; + }; + + struct EffectPipelineStateDescription + { + EffectPipelineStateDescription( + _In_ const D3D12_INPUT_LAYOUT_DESC* inputLayout, + _In_ const D3D12_BLEND_DESC* blend, + _In_ const D3D12_DEPTH_STENCIL_DESC* depthStencil, + _In_ const D3D12_RASTERIZER_DESC* rasterizer, + _In_ const RenderTargetState* renderTarget, + _In_opt_ D3D12_PRIMITIVE_TOPOLOGY_TYPE primitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, + _In_opt_ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE stripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED) + : + inputLayout(inputLayout), + blendDesc(blend), + depthStencilDesc(depthStencil), + rasterizerDesc(rasterizer), + renderTargetState(renderTarget), + primitiveTopology(primitiveTopology), + stripCutValue(stripCutValue) + { + // constructor + } + + const D3D12_INPUT_LAYOUT_DESC* inputLayout; + const D3D12_BLEND_DESC* blendDesc; + const D3D12_DEPTH_STENCIL_DESC* depthStencilDesc; + const D3D12_RASTERIZER_DESC* rasterizerDesc; + const RenderTargetState* renderTargetState; + const D3D12_PRIMITIVE_TOPOLOGY_TYPE primitiveTopology; + const D3D12_INDEX_BUFFER_STRIP_CUT_VALUE stripCutValue; + }; + + namespace EffectFlags + { + const int None = 0x00; + const int Fog = 0x01; + const int Lighting = 0x02; + const int PerPixelLighting = 0x04 | Lighting; // per pixel lighting implies lighting enabled + const int VertexColor = 0x08; + const int Texture = 0x10; + } + + //---------------------------------------------------------------------------------- + // Built-in shader supports optional texture mapping, vertex coloring, directional lighting, and fog. + class BasicEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog + { + public: + BasicEffect( _In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription ); + BasicEffect(BasicEffect&& moveFrom); + BasicEffect& operator= (BasicEffect&& moveFrom); + + BasicEffect(BasicEffect const&) = delete; + BasicEffect& operator= (BasicEffect const&) = delete; + + virtual ~BasicEffect(); + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* cmdList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void XM_CALLCONV SetSpecularColor(FXMVECTOR value); + void __cdecl SetSpecularPower(float value); + void __cdecl DisableSpecular(); + void __cdecl SetAlpha(float value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + // Built-in shader supports per-pixel alpha testing. + class AlphaTestEffect : public IEffect, public IEffectMatrices, public IEffectFog + { + public: + AlphaTestEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription, + D3D12_COMPARISON_FUNC alphaFunction = D3D12_COMPARISON_FUNC_GREATER); + AlphaTestEffect(AlphaTestEffect&& moveFrom); + AlphaTestEffect& operator= (AlphaTestEffect&& moveFrom); + + AlphaTestEffect(AlphaTestEffect const&) = delete; + AlphaTestEffect& operator= (AlphaTestEffect const&) = delete; + + virtual ~AlphaTestEffect(); + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* cmdList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + // Alpha test settings. + void __cdecl SetReferenceAlpha(int value); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + // Built-in shader supports two layer multitexturing (eg. for lightmaps or detail textures). + class DualTextureEffect : public IEffect, public IEffectMatrices, public IEffectFog + { + public: + DualTextureEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription); + DualTextureEffect(DualTextureEffect&& moveFrom); + DualTextureEffect& operator= (DualTextureEffect&& moveFrom); + + DualTextureEffect(DualTextureEffect const&) = delete; + DualTextureEffect& operator= (DualTextureEffect const&) = delete; + + ~DualTextureEffect(); + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* cmdList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Vertex color setting. + //void __cdecl SetVertexColorEnabled(bool value); + + // Texture settings. + void __cdecl SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + void __cdecl SetTexture2(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + // Built-in shader supports cubic environment mapping. + class EnvironmentMapEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog + { + public: + EnvironmentMapEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription, bool fresnelEnabled, bool specularEnabled); + EnvironmentMapEffect(EnvironmentMapEffect&& moveFrom); + EnvironmentMapEffect& operator= (EnvironmentMapEffect&& moveFrom); + + EnvironmentMapEffect(EnvironmentMapEffect const&) = delete; + EnvironmentMapEffect& operator= (EnvironmentMapEffect const&) = delete; + + virtual ~EnvironmentMapEffect(); + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* cmdList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void __cdecl SetAlpha(float value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(_In_opt_ D3D12_GPU_DESCRIPTOR_HANDLE value); + + // Environment map settings. + void __cdecl SetEnvironmentMap(_In_opt_ D3D12_GPU_DESCRIPTOR_HANDLE value); + void __cdecl SetEnvironmentMapAmount(float value); + void XM_CALLCONV SetEnvironmentMapSpecular(FXMVECTOR value); + void __cdecl SetFresnelFactor(float value); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + // Unsupported interface methods. + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + }; + + + // Built-in shader supports skinned animation. + class SkinnedEffect : public IEffect, public IEffectMatrices, public IEffectLights, public IEffectFog, public IEffectSkinning + { + public: + SkinnedEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription); + SkinnedEffect(SkinnedEffect&& moveFrom); + SkinnedEffect& operator= (SkinnedEffect&& moveFrom); + + SkinnedEffect(SkinnedEffect const&) = delete; + SkinnedEffect& operator= (SkinnedEffect const&) = delete; + + virtual ~SkinnedEffect(); + + // IEffect methods. + void __cdecl Apply(_In_ ID3D12GraphicsCommandList* commandList) override; + + // Camera settings. + void XM_CALLCONV SetWorld(FXMMATRIX value) override; + void XM_CALLCONV SetView(FXMMATRIX value) override; + void XM_CALLCONV SetProjection(FXMMATRIX value) override; + + // Material settings. + void XM_CALLCONV SetDiffuseColor(FXMVECTOR value); + void XM_CALLCONV SetEmissiveColor(FXMVECTOR value); + void XM_CALLCONV SetSpecularColor(FXMVECTOR value); + void __cdecl SetSpecularPower(float value); + void __cdecl DisableSpecular(); + void __cdecl SetAlpha(float value); + + // Light settings. + void XM_CALLCONV SetAmbientLightColor(FXMVECTOR value) override; + + void __cdecl SetLightEnabled(int whichLight, bool value) override; + void XM_CALLCONV SetLightDirection(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value) override; + void XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value) override; + + void __cdecl EnableDefaultLighting() override; + + // Fog settings. + void __cdecl SetFogStart(float value) override; + void __cdecl SetFogEnd(float value) override; + void XM_CALLCONV SetFogColor(FXMVECTOR value) override; + + // Texture setting. + void __cdecl SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor); + + // Animation settings. + void __cdecl SetWeightsPerVertex(int value) override; + void __cdecl SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) override; + void __cdecl ResetBoneTransforms() override; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + + + //---------------------------------------------------------------------------------- + // Abstract interface to factory texture resources + class IEffectTextureFactory + { + public: + virtual ~IEffectTextureFactory() {} + + virtual void __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) = 0; + }; + + class EffectTextureFactory : public IEffectTextureFactory + { + public: + EffectTextureFactory( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ ID3D12DescriptorHeap* descriptorHeap); + + EffectTextureFactory( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ size_t numDescriptors, + _In_ D3D12_DESCRIPTOR_HEAP_FLAGS descriptorHeapFlags); + + EffectTextureFactory(EffectTextureFactory&& moveFrom); + EffectTextureFactory& operator= (EffectTextureFactory&& moveFrom); + + EffectTextureFactory(EffectTextureFactory const&) = delete; + EffectTextureFactory& operator= (EffectTextureFactory const&) = delete; + + virtual ~EffectTextureFactory(); + + virtual void __cdecl CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) override; + + ID3D12DescriptorHeap* __cdecl DescriptorHeap() const; + + // Shorthand accessors for the descriptor heap + D3D12_CPU_DESCRIPTOR_HANDLE __cdecl GetCpuDescriptorHandle(size_t index) const; + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetGpuDescriptorHandle(size_t index) const; + + // How many textures are there in this factory? + size_t __cdecl ResourceCount() const; + + // Get a resource in a specific slot + void __cdecl GetResource(size_t slot, _Out_ ID3D12Resource** resource, _Out_ bool* isCubeMap); + + // Settings. + void __cdecl ReleaseCache(); + + void __cdecl SetSharing( bool enabled ); + + void __cdecl SetDirectory(_In_opt_z_ const wchar_t* path); + + private: + // Private implementation + class Impl; + + std::unique_ptr pImpl; + }; + + //---------------------------------------------------------------------------------- + // Abstract interface to factory for sharing effects and texture resources + class IEffectFactory + { + public: + virtual ~IEffectFactory() {} + + struct EffectInfo + { + std::wstring name; + bool perVertexColor; + bool enableSkinning; + bool enableDualTexture; + bool isPremultipliedAlpha; + float specularPower; + float alphaValue; + DirectX::XMFLOAT3 ambientColor; + DirectX::XMFLOAT3 diffuseColor; + DirectX::XMFLOAT3 specularColor; + DirectX::XMFLOAT3 emissiveColor; + int textureIndex; + int textureIndex2; + + EffectInfo() + : perVertexColor(false) + , enableSkinning(false) + , enableDualTexture(false) + , isPremultipliedAlpha(false) + , specularPower(0) + , alphaValue(0) + , ambientColor(0, 0, 0) + , diffuseColor(0, 0, 0) + , specularColor(0, 0, 0) + , emissiveColor(0, 0, 0) + , textureIndex(-1) + , textureIndex2(-1) + { + } + }; + + virtual std::shared_ptr __cdecl CreateEffect( _In_ const EffectInfo& info, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ const D3D12_INPUT_LAYOUT_DESC& inputLayout, + _In_opt_ int descriptorOffset = 0) = 0; + }; + + // Factory for sharing effects + class EffectFactory : public IEffectFactory + { + public: + EffectFactory(_In_ ID3D12Device* device); + EffectFactory(_In_ ID3D12DescriptorHeap* textureDescriptors); + + EffectFactory(EffectFactory&& moveFrom); + EffectFactory& operator= (EffectFactory&& moveFrom); + + EffectFactory(EffectFactory const&) = delete; + EffectFactory& operator= (EffectFactory const&) = delete; + + virtual ~EffectFactory(); + + // IEffectFactory methods. + virtual std::shared_ptr __cdecl CreateEffect( + _In_ const EffectInfo& info, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ const D3D12_INPUT_LAYOUT_DESC& inputLayout, + _In_opt_ int descriptorOffset = 0) override; + + // Settings. + void __cdecl ReleaseCache(); + + void __cdecl SetSharing( bool enabled ); + + private: + // Private implementation. + class Impl; + + std::shared_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/GamePad.h b/Kits/DirectXTK12/Inc/GamePad.h new file mode 100644 index 00000000..88d87922 --- /dev/null +++ b/Kits/DirectXTK12/Inc/GamePad.h @@ -0,0 +1,260 @@ +//-------------------------------------------------------------------------------------- +// File: GamePad.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if (_WIN32_WINNT < 0x0A00 /*_WIN32_WINNT_WIN10*/) +#ifndef _XBOX_ONE +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/ ) +#pragma comment(lib,"xinput.lib") +#else +#pragma comment(lib,"xinput9_1_0.lib") +#endif +#endif +#endif +#endif + +#include +#include + + +namespace DirectX +{ + class GamePad + { + public: + GamePad(); + GamePad(GamePad&& moveFrom); + GamePad& operator= (GamePad&& moveFrom); + + GamePad(GamePad const&) = delete; + GamePad& operator=(GamePad const&) = delete; + + virtual ~GamePad(); + +#if (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/ ) || defined(_XBOX_ONE) + static const int MAX_PLAYER_COUNT = 8; +#else + static const int MAX_PLAYER_COUNT = 4; +#endif + + enum DeadZone + { + DEAD_ZONE_INDEPENDENT_AXES = 0, + DEAD_ZONE_CIRCULAR, + DEAD_ZONE_NONE, + }; + + struct Buttons + { + bool a; + bool b; + bool x; + bool y; + bool leftStick; + bool rightStick; + bool leftShoulder; + bool rightShoulder; + union + { + bool back; + bool view; + }; + union + { + bool start; + bool menu; + }; + }; + + struct DPad + { + bool up; + bool down; + bool right; + bool left; + }; + + struct ThumbSticks + { + float leftX; + float leftY; + float rightX; + float rightY; + }; + + struct Triggers + { + float left; + float right; + }; + + struct State + { + bool connected; + uint64_t packet; + Buttons buttons; + DPad dpad; + ThumbSticks thumbSticks; + Triggers triggers; + + bool __cdecl IsConnected() const { return connected; } + + // Is the button pressed currently? + bool __cdecl IsAPressed() const { return buttons.a; } + bool __cdecl IsBPressed() const { return buttons.b; } + bool __cdecl IsXPressed() const { return buttons.x; } + bool __cdecl IsYPressed() const { return buttons.y; } + + bool __cdecl IsLeftStickPressed() const { return buttons.leftStick; } + bool __cdecl IsRightStickPressed() const { return buttons.rightStick; } + + bool __cdecl IsLeftShoulderPressed() const { return buttons.leftShoulder; } + bool __cdecl IsRightShoulderPressed() const { return buttons.rightShoulder; } + + bool __cdecl IsBackPressed() const { return buttons.back; } + bool __cdecl IsViewPressed() const { return buttons.view; } + bool __cdecl IsStartPressed() const { return buttons.start; } + bool __cdecl IsMenuPressed() const { return buttons.menu; } + + bool __cdecl IsDPadDownPressed() const { return dpad.down; }; + bool __cdecl IsDPadUpPressed() const { return dpad.up; }; + bool __cdecl IsDPadLeftPressed() const { return dpad.left; }; + bool __cdecl IsDPadRightPressed() const { return dpad.right; }; + + bool __cdecl IsLeftThumbStickUp() const { return (thumbSticks.leftY > 0.5f) != 0; } + bool __cdecl IsLeftThumbStickDown() const { return (thumbSticks.leftY < -0.5f) != 0; } + bool __cdecl IsLeftThumbStickLeft() const { return (thumbSticks.leftX < -0.5f) != 0; } + bool __cdecl IsLeftThumbStickRight() const { return (thumbSticks.leftX > 0.5f) != 0; } + + bool __cdecl IsRightThumbStickUp() const { return (thumbSticks.rightY > 0.5f ) != 0; } + bool __cdecl IsRightThumbStickDown() const { return (thumbSticks.rightY < -0.5f) != 0; } + bool __cdecl IsRightThumbStickLeft() const { return (thumbSticks.rightX < -0.5f) != 0; } + bool __cdecl IsRightThumbStickRight() const { return (thumbSticks.rightX > 0.5f) != 0; } + + bool __cdecl IsLeftTriggerPressed() const { return (triggers.left > 0.5f) != 0; } + bool __cdecl IsRightTriggerPressed() const { return (triggers.right > 0.5f) != 0; } + }; + + struct Capabilities + { + enum Type + { + UNKNOWN = 0, + GAMEPAD, + WHEEL, + ARCADE_STICK, + FLIGHT_STICK, + DANCE_PAD, + GUITAR, + GUITAR_ALTERNATE, + DRUM_KIT, + GUITAR_BASS = 11, + ARCADE_PAD = 19, + }; + + bool connected; + Type gamepadType; + uint64_t id; + + bool __cdecl IsConnected() const { return connected; } + }; + + class ButtonStateTracker + { + public: + enum ButtonState + { + UP = 0, // Button is up + HELD = 1, // Button is held down + RELEASED = 2, // Button was just released + PRESSED = 3, // Buton was just pressed + }; + + ButtonState a; + ButtonState b; + ButtonState x; + ButtonState y; + + ButtonState leftStick; + ButtonState rightStick; + + ButtonState leftShoulder; + ButtonState rightShoulder; + + union + { + ButtonState back; + ButtonState view; + }; + + union + { + ButtonState start; + ButtonState menu; + }; + + ButtonState dpadUp; + ButtonState dpadDown; + ButtonState dpadLeft; + ButtonState dpadRight; + + ButtonState leftStickUp; + ButtonState leftStickDown; + ButtonState leftStickLeft; + ButtonState leftStickRight; + + ButtonState rightStickUp; + ButtonState rightStickDown; + ButtonState rightStickLeft; + ButtonState rightStickRight; + + ButtonState leftTrigger; + ButtonState rightTrigger; + + ButtonStateTracker() { Reset(); } + + void __cdecl Update( const State& state ); + + void __cdecl Reset(); + + State __cdecl GetLastState() const { return lastState; } + + private: + State lastState; + }; + + // Retrieve the current state of the gamepad of the associated player index + State __cdecl GetState(int player, DeadZone deadZoneMode = DEAD_ZONE_INDEPENDENT_AXES); + + // Retrieve the current capabilities of the gamepad of the associated player index + Capabilities __cdecl GetCapabilities(int player); + + // Set the vibration motor speeds of the gamepad + bool __cdecl SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger = 0.f, float rightTrigger = 0.f ); + + // Handle suspending/resuming + void __cdecl Suspend(); + void __cdecl Resume(); + + // Singleton + static GamePad& __cdecl Get(); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/GeometricPrimitive.h b/Kits/DirectXTK12/Inc/GeometricPrimitive.h new file mode 100644 index 00000000..8f89f9b5 --- /dev/null +++ b/Kits/DirectXTK12/Inc/GeometricPrimitive.h @@ -0,0 +1,75 @@ +//-------------------------------------------------------------------------------------- +// File: GeometricPrimitive.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "VertexTypes.h" + +#include +#include + + +namespace DirectX +{ + class IEffect; + + class GeometricPrimitive + { + public: + GeometricPrimitive(GeometricPrimitive const&) = delete; + GeometricPrimitive& operator= (GeometricPrimitive const&) = delete; + + virtual ~GeometricPrimitive(); + + using VertexType = VertexPositionNormalTexture; + + // Factory methods. + static std::unique_ptr __cdecl CreateCube(float size = 1, bool rhcoords = true); + static std::unique_ptr __cdecl CreateBox(const XMFLOAT3& size, bool rhcoords = true, bool invertn = false); + static std::unique_ptr __cdecl CreateSphere(float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false); + static std::unique_ptr __cdecl CreateGeoSphere(float diameter = 1, size_t tessellation = 3, bool rhcoords = true); + static std::unique_ptr __cdecl CreateCylinder(float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true); + static std::unique_ptr __cdecl CreateCone(float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true); + static std::unique_ptr __cdecl CreateTorus(float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true); + static std::unique_ptr __cdecl CreateTetrahedron(float size = 1, bool rhcoords = true); + static std::unique_ptr __cdecl CreateOctahedron(float size = 1, bool rhcoords = true); + static std::unique_ptr __cdecl CreateDodecahedron(float size = 1, bool rhcoords = true); + static std::unique_ptr __cdecl CreateIcosahedron(float size = 1, bool rhcoords = true); + static std::unique_ptr __cdecl CreateTeapot(float size = 1, size_t tessellation = 8, bool rhcoords = true); + static std::unique_ptr __cdecl CreateCustom(const std::vector& vertices, const std::vector& indices); + + static void __cdecl CreateCube(std::vector& vertices, std::vector& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateBox(std::vector& vertices, std::vector& indices, const XMFLOAT3& size, bool rhcoords = true, bool invertn = false); + static void __cdecl CreateSphere(std::vector& vertices, std::vector& indices, float diameter = 1, size_t tessellation = 16, bool rhcoords = true, bool invertn = false); + static void __cdecl CreateGeoSphere(std::vector& vertices, std::vector& indices, float diameter = 1, size_t tessellation = 3, bool rhcoords = true); + static void __cdecl CreateCylinder(std::vector& vertices, std::vector& indices, float height = 1, float diameter = 1, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateCone(std::vector& vertices, std::vector& indices, float diameter = 1, float height = 1, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateTorus(std::vector& vertices, std::vector& indices, float diameter = 1, float thickness = 0.333f, size_t tessellation = 32, bool rhcoords = true); + static void __cdecl CreateTetrahedron(std::vector& vertices, std::vector& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateOctahedron(std::vector& vertices, std::vector& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateDodecahedron(std::vector& vertices, std::vector& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateIcosahedron(std::vector& vertices, std::vector& indices, float size = 1, bool rhcoords = true); + static void __cdecl CreateTeapot(std::vector& vertices, std::vector& indices, float size = 1, size_t tessellation = 8, bool rhcoords = true); + + // Draw the primitive. + void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList); + + private: + GeometricPrimitive(); + + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/GraphicsMemory.h b/Kits/DirectXTK12/Inc/GraphicsMemory.h new file mode 100644 index 00000000..862e77f7 --- /dev/null +++ b/Kits/DirectXTK12/Inc/GraphicsMemory.h @@ -0,0 +1,122 @@ +//-------------------------------------------------------------------------------------- +// File: GraphicsMemory.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include + + +namespace DirectX +{ + class LinearAllocatorPage; + + // Works a little like a smart pointer. The memory will only be fenced by the GPU once the pointer + // has been invalidated or the user explicitly marks it for fencing. + class GraphicsResource + { + public: + GraphicsResource(); + GraphicsResource( + _In_ LinearAllocatorPage* page, + _In_ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress, + _In_ ID3D12Resource* resource, + _In_ void* memory, + _In_ size_t offset, + _In_ size_t size); + + GraphicsResource(GraphicsResource&& other); + GraphicsResource&& operator= (GraphicsResource&&); + + GraphicsResource(const GraphicsResource&) = delete; + GraphicsResource& operator= (const GraphicsResource&) = delete; + + ~GraphicsResource(); + + D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const { return mGpuAddress; } + ID3D12Resource* Resource() const { return mResource; } + void* Memory() const { return mMemory; } + size_t ResourceOffset() const { return mBufferOffset; } + size_t Size() const { return mSize; } + + // Clear the pointer. Using operator -> will produce bad results. + void __cdecl Reset(); + void __cdecl Reset(GraphicsResource&&); + + private: + LinearAllocatorPage* mPage; + D3D12_GPU_VIRTUAL_ADDRESS mGpuAddress; + ID3D12Resource* mResource; + void* mMemory; + size_t mBufferOffset; + size_t mSize; + }; + + class GraphicsMemory + { + public: + explicit GraphicsMemory(_In_ ID3D12Device* device); + + GraphicsMemory(GraphicsMemory&& moveFrom); + GraphicsMemory& operator= (GraphicsMemory&& moveFrom); + + GraphicsMemory(GraphicsMemory const&) = delete; + GraphicsMemory& operator=(GraphicsMemory const&) = delete; + + virtual ~GraphicsMemory(); + + // Make sure to keep the GraphicsResource handle alive as long as you need to access + // the memory on the CPU. For example, do not simply cache GpuAddress() and discard + // the GraphicsResource object, or your memory may be overwritten later. + GraphicsResource __cdecl Allocate(size_t size, size_t alignment = 0); + + // Special overload of Allocate that aligns to D3D12 constant buffer alignment requirements + template GraphicsResource AllocateConstant() + { + const size_t alignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; + const size_t alignedSize = (sizeof(T) + alignment - 1) & ~(alignment - 1); + return std::move(Allocate(alignedSize, alignment)); + } + template GraphicsResource AllocateConstant(const T& setData) + { + GraphicsResource alloc = AllocateConstant(); + memcpy(alloc.Memory(), &setData, sizeof(T)); + return std::move(alloc); + } + + // Submits all the pending one-shot memory to the GPU. + // The memory will be recycled once the GPU is done with it. + void __cdecl Commit(_In_ ID3D12CommandQueue* commandQueue); + + // This frees up any unused memory. + // If you want to make sure all memory is reclaimed, idle the GPU before calling this. + // It is not recommended that you call this unless absolutely necessary (e.g. your + // memory budget changes at run-time, or perhaps you're changing levels in your game.) + void __cdecl GarbageCollect(); + + // Singleton + static GraphicsMemory& __cdecl Get(); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} + diff --git a/Kits/DirectXTK12/Inc/Keyboard.h b/Kits/DirectXTK12/Inc/Keyboard.h new file mode 100644 index 00000000..d224f67d --- /dev/null +++ b/Kits/DirectXTK12/Inc/Keyboard.h @@ -0,0 +1,479 @@ +//-------------------------------------------------------------------------------------- +// File: Keyboard.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +namespace ABI { namespace Windows { namespace UI { namespace Core { struct ICoreWindow; } } } } +#endif + + +namespace DirectX +{ + class Keyboard + { + public: + Keyboard(); + Keyboard(Keyboard&& moveFrom); + Keyboard& operator= (Keyboard&& moveFrom); + + Keyboard(Keyboard const&) = delete; + Keyboard& operator=(Keyboard const&) = delete; + + virtual ~Keyboard(); + + enum Keys + { + None = 0, + + Back = 0x8, + Tab = 0x9, + + Enter = 0xd, + + Pause = 0x13, + CapsLock = 0x14, + Kana = 0x15, + + Kanji = 0x19, + + Escape = 0x1b, + ImeConvert = 0x1c, + ImeNoConvert = 0x1d, + + Space = 0x20, + PageUp = 0x21, + PageDown = 0x22, + End = 0x23, + Home = 0x24, + Left = 0x25, + Up = 0x26, + Right = 0x27, + Down = 0x28, + Select = 0x29, + Print = 0x2a, + Execute = 0x2b, + PrintScreen = 0x2c, + Insert = 0x2d, + Delete = 0x2e, + Help = 0x2f, + D0 = 0x30, + D1 = 0x31, + D2 = 0x32, + D3 = 0x33, + D4 = 0x34, + D5 = 0x35, + D6 = 0x36, + D7 = 0x37, + D8 = 0x38, + D9 = 0x39, + + A = 0x41, + B = 0x42, + C = 0x43, + D = 0x44, + E = 0x45, + F = 0x46, + G = 0x47, + H = 0x48, + I = 0x49, + J = 0x4a, + K = 0x4b, + L = 0x4c, + M = 0x4d, + N = 0x4e, + O = 0x4f, + P = 0x50, + Q = 0x51, + R = 0x52, + S = 0x53, + T = 0x54, + U = 0x55, + V = 0x56, + W = 0x57, + X = 0x58, + Y = 0x59, + Z = 0x5a, + LeftWindows = 0x5b, + RightWindows = 0x5c, + Apps = 0x5d, + + Sleep = 0x5f, + NumPad0 = 0x60, + NumPad1 = 0x61, + NumPad2 = 0x62, + NumPad3 = 0x63, + NumPad4 = 0x64, + NumPad5 = 0x65, + NumPad6 = 0x66, + NumPad7 = 0x67, + NumPad8 = 0x68, + NumPad9 = 0x69, + Multiply = 0x6a, + Add = 0x6b, + Separator = 0x6c, + Subtract = 0x6d, + + Decimal = 0x6e, + Divide = 0x6f, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7a, + F12 = 0x7b, + F13 = 0x7c, + F14 = 0x7d, + F15 = 0x7e, + F16 = 0x7f, + F17 = 0x80, + F18 = 0x81, + F19 = 0x82, + F20 = 0x83, + F21 = 0x84, + F22 = 0x85, + F23 = 0x86, + F24 = 0x87, + + NumLock = 0x90, + Scroll = 0x91, + + LeftShift = 0xa0, + RightShift = 0xa1, + LeftControl = 0xa2, + RightControl = 0xa3, + LeftAlt = 0xa4, + RightAlt = 0xa5, + BrowserBack = 0xa6, + BrowserForward = 0xa7, + BrowserRefresh = 0xa8, + BrowserStop = 0xa9, + BrowserSearch = 0xaa, + BrowserFavorites = 0xab, + BrowserHome = 0xac, + VolumeMute = 0xad, + VolumeDown = 0xae, + VolumeUp = 0xaf, + MediaNextTrack = 0xb0, + MediaPreviousTrack = 0xb1, + MediaStop = 0xb2, + MediaPlayPause = 0xb3, + LaunchMail = 0xb4, + SelectMedia = 0xb5, + LaunchApplication1 = 0xb6, + LaunchApplication2 = 0xb7, + + OemSemicolon = 0xba, + OemPlus = 0xbb, + OemComma = 0xbc, + OemMinus = 0xbd, + OemPeriod = 0xbe, + OemQuestion = 0xbf, + OemTilde = 0xc0, + + OemOpenBrackets = 0xdb, + OemPipe = 0xdc, + OemCloseBrackets = 0xdd, + OemQuotes = 0xde, + Oem8 = 0xdf, + + OemBackslash = 0xe2, + + ProcessKey = 0xe5, + + OemCopy = 0xf2, + OemAuto = 0xf3, + OemEnlW = 0xf4, + + Attn = 0xf6, + Crsel = 0xf7, + Exsel = 0xf8, + EraseEof = 0xf9, + Play = 0xfa, + Zoom = 0xfb, + + Pa1 = 0xfd, + OemClear = 0xfe, + }; + + struct State + { + bool Reserved0 : 8; + bool Back : 1; // VK_BACK, 0x8 + bool Tab : 1; // VK_TAB, 0x9 + bool Reserved1 : 3; + bool Enter : 1; // VK_RETURN, 0xD + bool Reserved2 : 2; + bool Reserved3 : 3; + bool Pause : 1; // VK_PAUSE, 0x13 + bool CapsLock : 1; // VK_CAPITAL, 0x14 + bool Kana : 1; // VK_KANA, 0x15 + bool Reserved4 : 2; + bool Reserved5 : 1; + bool Kanji : 1; // VK_KANJI, 0x19 + bool Reserved6 : 1; + bool Escape : 1; // VK_ESCAPE, 0x1B + bool ImeConvert : 1; // VK_CONVERT, 0x1C + bool ImeNoConvert : 1; // VK_NONCONVERT, 0x1D + bool Reserved7 : 2; + bool Space : 1; // VK_SPACE, 0x20 + bool PageUp : 1; // VK_PRIOR, 0x21 + bool PageDown : 1; // VK_NEXT, 0x22 + bool End : 1; // VK_END, 0x23 + bool Home : 1; // VK_HOME, 0x24 + bool Left : 1; // VK_LEFT, 0x25 + bool Up : 1; // VK_UP, 0x26 + bool Right : 1; // VK_RIGHT, 0x27 + bool Down : 1; // VK_DOWN, 0x28 + bool Select : 1; // VK_SELECT, 0x29 + bool Print : 1; // VK_PRINT, 0x2A + bool Execute : 1; // VK_EXECUTE, 0x2B + bool PrintScreen : 1; // VK_SNAPSHOT, 0x2C + bool Insert : 1; // VK_INSERT, 0x2D + bool Delete : 1; // VK_DELETE, 0x2E + bool Help : 1; // VK_HELP, 0x2F + bool D0 : 1; // 0x30 + bool D1 : 1; // 0x31 + bool D2 : 1; // 0x32 + bool D3 : 1; // 0x33 + bool D4 : 1; // 0x34 + bool D5 : 1; // 0x35 + bool D6 : 1; // 0x36 + bool D7 : 1; // 0x37 + bool D8 : 1; // 0x38 + bool D9 : 1; // 0x39 + bool Reserved8 : 6; + bool Reserved9 : 1; + bool A : 1; // 0x41 + bool B : 1; // 0x42 + bool C : 1; // 0x43 + bool D : 1; // 0x44 + bool E : 1; // 0x45 + bool F : 1; // 0x46 + bool G : 1; // 0x47 + bool H : 1; // 0x48 + bool I : 1; // 0x49 + bool J : 1; // 0x4A + bool K : 1; // 0x4B + bool L : 1; // 0x4C + bool M : 1; // 0x4D + bool N : 1; // 0x4E + bool O : 1; // 0x4F + bool P : 1; // 0x50 + bool Q : 1; // 0x51 + bool R : 1; // 0x52 + bool S : 1; // 0x53 + bool T : 1; // 0x54 + bool U : 1; // 0x55 + bool V : 1; // 0x56 + bool W : 1; // 0x57 + bool X : 1; // 0x58 + bool Y : 1; // 0x59 + bool Z : 1; // 0x5A + bool LeftWindows : 1; // VK_LWIN, 0x5B + bool RightWindows : 1; // VK_RWIN, 0x5C + bool Apps : 1; // VK_APPS, 0x5D + bool Reserved10 : 1; + bool Sleep : 1; // VK_SLEEP, 0x5F + bool NumPad0 : 1; // VK_NUMPAD0, 0x60 + bool NumPad1 : 1; // VK_NUMPAD1, 0x61 + bool NumPad2 : 1; // VK_NUMPAD2, 0x62 + bool NumPad3 : 1; // VK_NUMPAD3, 0x63 + bool NumPad4 : 1; // VK_NUMPAD4, 0x64 + bool NumPad5 : 1; // VK_NUMPAD5, 0x65 + bool NumPad6 : 1; // VK_NUMPAD6, 0x66 + bool NumPad7 : 1; // VK_NUMPAD7, 0x67 + bool NumPad8 : 1; // VK_NUMPAD8, 0x68 + bool NumPad9 : 1; // VK_NUMPAD9, 0x69 + bool Multiply : 1; // VK_MULTIPLY, 0x6A + bool Add : 1; // VK_ADD, 0x6B + bool Separator : 1; // VK_SEPARATOR, 0x6C + bool Subtract : 1; // VK_SUBTRACT, 0x6D + bool Decimal : 1; // VK_DECIMANL, 0x6E + bool Divide : 1; // VK_DIVIDE, 0x6F + bool F1 : 1; // VK_F1, 0x70 + bool F2 : 1; // VK_F2, 0x71 + bool F3 : 1; // VK_F3, 0x72 + bool F4 : 1; // VK_F4, 0x73 + bool F5 : 1; // VK_F5, 0x74 + bool F6 : 1; // VK_F6, 0x75 + bool F7 : 1; // VK_F7, 0x76 + bool F8 : 1; // VK_F8, 0x77 + bool F9 : 1; // VK_F9, 0x78 + bool F10 : 1; // VK_F10, 0x79 + bool F11 : 1; // VK_F11, 0x7A + bool F12 : 1; // VK_F12, 0x7B + bool F13 : 1; // VK_F13, 0x7C + bool F14 : 1; // VK_F14, 0x7D + bool F15 : 1; // VK_F15, 0x7E + bool F16 : 1; // VK_F16, 0x7F + bool F17 : 1; // VK_F17, 0x80 + bool F18 : 1; // VK_F18, 0x81 + bool F19 : 1; // VK_F19, 0x82 + bool F20 : 1; // VK_F20, 0x83 + bool F21 : 1; // VK_F21, 0x84 + bool F22 : 1; // VK_F22, 0x85 + bool F23 : 1; // VK_F23, 0x86 + bool F24 : 1; // VK_F24, 0x87 + bool Reserved11 : 8; + bool NumLock : 1; // VK_NUMLOCK, 0x90 + bool Scroll : 1; // VK_SCROLL, 0x91 + bool Reserved12 : 6; + bool Reserved13 : 8; + bool LeftShift : 1; // VK_LSHIFT, 0xA0 + bool RightShift : 1; // VK_RSHIFT, 0xA1 + bool LeftControl : 1; // VK_LCONTROL, 0xA2 + bool RightControl : 1; // VK_RCONTROL, 0xA3 + bool LeftAlt : 1; // VK_LMENU, 0xA4 + bool RightAlt : 1; // VK_RMENU, 0xA5 + bool BrowserBack : 1; // VK_BROWSER_BACK, 0xA6 + bool BrowserForward : 1; // VK_BROWSER_FORWARD, 0xA7 + bool BrowserRefresh : 1; // VK_BROWSER_REFRESH, 0xA8 + bool BrowserStop : 1; // VK_BROWSER_STOP, 0xA9 + bool BrowserSearch : 1; // VK_BROWSER_SEARCH, 0xAA + bool BrowserFavorites : 1; // VK_BROWSER_FAVORITES, 0xAB + bool BrowserHome : 1; // VK_BROWSER_HOME, 0xAC + bool VolumeMute : 1; // VK_VOLUME_MUTE, 0xAD + bool VolumeDown : 1; // VK_VOLUME_DOWN, 0xAE + bool VolumeUp : 1; // VK_VOLUME_UP, 0xAF + bool MediaNextTrack : 1; // VK_MEDIA_NEXT_TRACK, 0xB0 + bool MediaPreviousTrack : 1;// VK_MEDIA_PREV_TRACK, 0xB1 + bool MediaStop : 1; // VK_MEDIA_STOP, 0xB2 + bool MediaPlayPause : 1; // VK_MEDIA_PLAY_PAUSE, 0xB3 + bool LaunchMail : 1; // VK_LAUNCH_MAIL, 0xB4 + bool SelectMedia : 1; // VK_LAUNCH_MEDIA_SELECT, 0xB5 + bool LaunchApplication1 : 1;// VK_LAUNCH_APP1, 0xB6 + bool LaunchApplication2 : 1;// VK_LAUNCH_APP2, 0xB7 + bool Reserved14 : 2; + bool OemSemicolon : 1; // VK_OEM_1, 0xBA + bool OemPlus : 1; // VK_OEM_PLUS, 0xBB + bool OemComma : 1; // VK_OEM_COMMA, 0xBC + bool OemMinus : 1; // VK_OEM_MINUS, 0xBD + bool OemPeriod : 1; // VK_OEM_PERIOD, 0xBE + bool OemQuestion : 1; // VK_OEM_2, 0xBF + bool OemTilde : 1; // VK_OEM_3, 0xC0 + bool Reserved15 : 7; + bool Reserved16 : 8; + bool Reserved17 : 8; + bool Reserved18 : 3; + bool OemOpenBrackets : 1; // VK_OEM_4, 0xDB + bool OemPipe : 1; // VK_OEM_5, 0xDC + bool OemCloseBrackets : 1; // VK_OEM_6, 0xDD + bool OemQuotes : 1; // VK_OEM_7, 0xDE + bool Oem8 : 1; // VK_OEM_8, 0xDF + bool Reserved19 : 2; + bool OemBackslash : 1; // VK_OEM_102, 0xE2 + bool Reserved20 : 2; + bool ProcessKey : 1; // VK_PROCESSKEY, 0xE5 + bool Reserved21 : 2; + bool Reserved22 : 8; + bool Reserved23 : 2; + bool OemCopy : 1; // 0XF2 + bool OemAuto : 1; // 0xF3 + bool OemEnlW : 1; // 0xF4 + bool Reserved24 : 1; + bool Attn : 1; // VK_ATTN, 0xF6 + bool Crsel : 1; // VK_CRSEL, 0xF7 + bool Exsel : 1; // VK_EXSEL, 0xF8 + bool EraseEof : 1; // VK_EREOF, 0xF9 + bool Play : 1; // VK_PLAY, 0xFA + bool Zoom : 1; // VK_ZOOM, 0xFB + bool Reserved25 : 1; + bool Pa1 : 1; // VK_PA1, 0xFD + bool OemClear : 1; // VK_OEM_CLEAR, 0xFE + bool Reserved26: 1; + + bool __cdecl IsKeyDown(Keys key) const + { + if (key >= 0 && key <= 0xff) + { + auto ptr = reinterpret_cast(this); + unsigned int bf = 1u << (key & 0x1f); + return (ptr[(key >> 5)] & bf) != 0; + } + return false; + } + + bool __cdecl IsKeyUp(Keys key) const + { + if (key >= 0 && key <= 0xfe) + { + auto ptr = reinterpret_cast(this); + unsigned int bf = 1u << (key & 0x1f); + return (ptr[(key >> 5)] & bf) == 0; + } + return false; + } + }; + + class KeyboardStateTracker + { + public: + State released; + State pressed; + + KeyboardStateTracker() { Reset(); } + + void __cdecl Update(const State& state); + + void __cdecl Reset(); + + bool __cdecl IsKeyPressed(Keys key) const { return pressed.IsKeyDown(key); } + bool __cdecl IsKeyReleased(Keys key) const { return released.IsKeyDown(key); } + + State __cdecl GetLastState() const { return lastState; } + + public: + State lastState; + }; + + // Retrieve the current state of the keyboard + State __cdecl GetState() const; + + // Reset the keyboard state + void __cdecl Reset(); + +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) && defined(WM_USER) + static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) + void __cdecl SetWindow(ABI::Windows::UI::Core::ICoreWindow* window); +#ifdef __cplusplus_winrt + void __cdecl SetWindow(Windows::UI::Core::CoreWindow^ window) + { + // See https://msdn.microsoft.com/en-us/library/hh755802.aspx + SetWindow(reinterpret_cast(window)); + } +#endif +#endif + + // Singleton + static Keyboard& __cdecl Get(); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/Model.h b/Kits/DirectXTK12/Inc/Model.h new file mode 100644 index 00000000..d003abfe --- /dev/null +++ b/Kits/DirectXTK12/Inc/Model.h @@ -0,0 +1,287 @@ +//-------------------------------------------------------------------------------------- +// File: Model.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GraphicsMemory.h" +#include "Effects.h" + + +namespace DirectX +{ + class IEffect; + class IEffectFactory; + class CommonStates; + class ModelMesh; + + //---------------------------------------------------------------------------------- + // Each mesh part is a submesh with a single effect + class ModelMeshPart + { + public: + ModelMeshPart(); + virtual ~ModelMeshPart(); + + uint32_t materialIndex; + uint32_t indexCount; + uint32_t startIndex; + uint32_t vertexOffset; + uint32_t vertexStride; + D3D_PRIMITIVE_TOPOLOGY primitiveType; + DXGI_FORMAT indexFormat; + GraphicsResource indexBuffer; + GraphicsResource vertexBuffer; + std::shared_ptr> vbDecl; + bool isAlpha; + + using Collection = std::vector>; + using DrawCallback = std::function; + + // Draw mesh part + void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; + + // + // Utilities for drawing multiple mesh parts + // + + // Draw the mesh + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, _In_ const ModelMeshPart::Collection& meshParts); + + // Draw the mesh with an effect + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, _In_ const ModelMeshPart::Collection& meshParts, _In_ IEffect* effect); + + // Draw the mesh with a callback for each mesh part + static void __cdecl DrawMeshParts(_In_ ID3D12GraphicsCommandList* commandList, _In_ const ModelMeshPart::Collection& meshParts, DrawCallback callback); + + // Draw the mesh with a range of effects that mesh parts will index into. + // Effects can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. + // The iterator passed to this method should have random access capabilities for best performance. + template + static void DrawMeshParts( + _In_ ID3D12GraphicsCommandList* commandList, + _In_ const ModelMeshPart::Collection& meshParts, + TEffectIterator effects) + { + // This assert is here to prevent accidental use of containers that would cause undesirable performance penalties. + static_assert( + std::is_base_of::value, + "Providing an iterator without random access capabilities -- such as from std::list -- is not supported."); + + for ( auto it = std::begin(meshParts); it != std::end(meshParts); ++it ) + { + auto part = it->get(); + assert(part != nullptr); + + // Get the effect at the location specified by the part's material + TEffectIterator effect_iterator = effects; + std::advance(effect_iterator, part->materialIndex); + + // Apply the effect and draw + (*effect_iterator)->Apply(commandList); + part->Draw(commandList); + } + } + }; + + + //---------------------------------------------------------------------------------- + // A mesh consists of one or more model mesh parts + class ModelMesh + { + public: + ModelMesh(); + virtual ~ModelMesh(); + + BoundingSphere boundingSphere; + BoundingBox boundingBox; + ModelMeshPart::Collection opaqueMeshParts; + ModelMeshPart::Collection alphaMeshParts; + std::wstring name; + bool ccw; + bool pmalpha; + + using Collection = std::vector>; + + // Draw the mesh + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList) const; + + // Draw the mesh with an effect + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const; + + // Draw the mesh with a callback for each mesh part + void __cdecl DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; + void __cdecl DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const; + + // Draw the mesh with a range of effects that mesh parts will index into. + // TEffectPtr can be any IEffect pointer type (including smart pointer). Value or reference types will not compile. + template + void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const + { + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, effects); + } + template + void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, TEffectIterator effects) const + { + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, effects); + } + }; + + + //---------------------------------------------------------------------------------- + // A model consists of one or more meshes + class Model + { + public: + Model(); + virtual ~Model(); + + using ModelMaterialInfo = IEffectFactory::EffectInfo; + using ModelMaterialInfoCollection = std::vector; + using TextureCollection = std::vector; + + // + // NOTE + // + // The Model::Draw functions use variadic templates and perfect-forwarding in order to support future overloads to the ModelMesh::Draw + // family of functions. This means that a new ModelMesh::Draw overload can be added, removed or altered, but the Model::Draw* routines + // will still remain compatible. The correct ModelMesh::Draw overload will be selected by the compiler depending on the arguments you + // provide to Model::Draw*. + // + + // Draw all the opaque meshes in the model + template void DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, _In_opt_ TForwardArgs&&... args) const + { + // Draw opaque parts + for ( auto it = std::begin(meshes); it != std::end(meshes); ++it ) + { + auto mesh = it->get(); + assert( mesh != nullptr ); + + mesh->DrawOpaque(commandList, std::forward(args)...); + } + } + + // Draw all the alpha meshes in the model + template void DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, _In_opt_ TForwardArgs&&... args) const + { + // Draw opaque parts + for ( auto it = std::begin(meshes); it != std::end(meshes); ++it ) + { + auto mesh = it->get(); + assert( mesh != nullptr ); + + mesh->DrawAlpha(commandList, std::forward(args)...); + } + } + + // Draw all the meshes in the model + template void Draw(_In_ ID3D12GraphicsCommandList* commandList, _In_opt_ TForwardArgs&&... args) const + { + DrawOpaque(commandList, std::forward(args)...); + DrawAlpha(commandList, std::forward(args)...); + } + + // Load texture resources into an existing Effect Texture Factory + void __cdecl LoadTextures(_In_ IEffectTextureFactory& texFactory, _In_opt_ int destinationDescriptorOffset = 0); + + // Load texture resources into a new Effect Texture Factory + std::unique_ptr __cdecl LoadTextures( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_opt_z_ const wchar_t* texturesPath = nullptr, + _In_opt_ D3D12_DESCRIPTOR_HEAP_FLAGS flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + + // Create effects using the default effect factory + std::vector> __cdecl CreateEffects( + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ ID3D12DescriptorHeap* gpuVisibleTextureDescriptorHeap, + _In_opt_ int baseDescriptorOffset = 0); + + // Create effects using a custom effect factory + std::vector> __cdecl CreateEffects( + _In_ IEffectFactory& fxFactory, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_opt_ int baseDescriptorOffset = 0); + + // Loads a model from a DirectX SDK .SDKMESH file + static std::unique_ptr __cdecl CreateFromSDKMESH( _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, + bool ccw = false, bool pmalpha = false ); + static std::unique_ptr __cdecl CreateFromSDKMESH( _In_z_ const wchar_t* szFileName, + bool ccw = false, bool pmalpha = false ); + + // Loads a model from a .VBO file + static std::unique_ptr __cdecl CreateFromVBO( _In_reads_bytes_(dataSize) const uint8_t* meshData, _In_ size_t dataSize, + bool ccw = false, bool pmalpha = false ); + static std::unique_ptr __cdecl CreateFromVBO( _In_z_ const wchar_t* szFileName, + bool ccw = false, bool pmalpha = false ); + + // Utility function for getting a GPU descriptor for a mesh part/material index. If there is no texture the + // descriptor will be zero. + D3D12_GPU_DESCRIPTOR_HANDLE GetGpuTextureHandleForMaterialIndex(uint32_t materialIndex, _In_ ID3D12DescriptorHeap* heap, _In_ size_t descriptorSize, _In_ size_t descriptorOffset) const + { + D3D12_GPU_DESCRIPTOR_HANDLE handle = {}; + + if (materialIndex >= materials.size()) + return handle; + + int textureIndex = materials[materialIndex].textureIndex; + if (textureIndex == -1) + return handle; + + handle = heap->GetGPUDescriptorHandleForHeapStart(); + handle.ptr += descriptorSize * ((size_t) textureIndex + descriptorOffset); + + return handle; + } + + // Utility function for updating the matrices in a list of effects. This will SetWorld, SetView and SetProjection + // on any effect in the list that derives from IEffectMatrices. + static void XM_CALLCONV UpdateEffectMatrices( + _In_ std::vector>& effectList, + DirectX::FXMMATRIX world, + DirectX::CXMMATRIX view, + DirectX::CXMMATRIX proj); + + ModelMesh::Collection meshes; + ModelMaterialInfoCollection materials; + TextureCollection textureNames; + std::wstring name; + + private: + std::shared_ptr __cdecl CreateEffectForMeshPart( + _In_ IEffectFactory& fxFactory, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_opt_ int descriptorOffset, + _In_ const ModelMeshPart* part) const; + }; + } diff --git a/Kits/DirectXTK12/Inc/Mouse.h b/Kits/DirectXTK12/Inc/Mouse.h new file mode 100644 index 00000000..6e04e3f5 --- /dev/null +++ b/Kits/DirectXTK12/Inc/Mouse.h @@ -0,0 +1,120 @@ +//-------------------------------------------------------------------------------------- +// File: Mouse.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +namespace ABI { namespace Windows { namespace UI { namespace Core { struct ICoreWindow; } } } } +#endif + + +namespace DirectX +{ + class Mouse + { + public: + Mouse(); + Mouse(Mouse&& moveFrom); + Mouse& operator= (Mouse&& moveFrom); + + Mouse(Mouse const&) = delete; + Mouse& operator=(Mouse const&) = delete; + + virtual ~Mouse(); + + enum Mode + { + MODE_ABSOLUTE = 0, + MODE_RELATIVE, + }; + + struct State + { + bool leftButton; + bool middleButton; + bool rightButton; + bool xButton1; + bool xButton2; + int x; + int y; + int scrollWheelValue; + Mode positionMode; + }; + + class ButtonStateTracker + { + public: + enum ButtonState + { + UP = 0, // Button is up + HELD = 1, // Button is held down + RELEASED = 2, // Button was just released + PRESSED = 3, // Buton was just pressed + }; + + ButtonState leftButton; + ButtonState middleButton; + ButtonState rightButton; + ButtonState xButton1; + ButtonState xButton2; + + ButtonStateTracker() { Reset(); } + + void __cdecl Update( const State& state ); + + void __cdecl Reset(); + + State __cdecl GetLastState() const { return lastState; } + + private: + State lastState; + }; + + // Retrieve the current state of the mouse + State __cdecl GetState() const; + + // Resets the accumulated scroll wheel value + void __cdecl ResetScrollWheelValue(); + + // Sets mouse mode (defaults to absolute) + void __cdecl SetMode(Mode mode); + +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) && defined(WM_USER) + void __cdecl SetWindow(HWND window); + static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) + void __cdecl SetWindow(ABI::Windows::UI::Core::ICoreWindow* window); +#ifdef __cplusplus_winrt + void __cdecl SetWindow(Windows::UI::Core::CoreWindow^ window) + { + // See https://msdn.microsoft.com/en-us/library/hh755802.aspx + SetWindow(reinterpret_cast(window)); + } +#endif + static void __cdecl SetDpi(float dpi); +#endif + + // Singleton + static Mouse& __cdecl Get(); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; +} diff --git a/Kits/DirectXTK12/Inc/PrimitiveBatch.h b/Kits/DirectXTK12/Inc/PrimitiveBatch.h new file mode 100644 index 00000000..f068e146 --- /dev/null +++ b/Kits/DirectXTK12/Inc/PrimitiveBatch.h @@ -0,0 +1,144 @@ +//-------------------------------------------------------------------------------------- +// File: PrimitiveBatch.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include + + +namespace DirectX +{ + namespace Internal + { + // Base class, not to be used directly: clients should access this via the derived PrimitiveBatch. + class PrimitiveBatchBase + { + protected: + PrimitiveBatchBase(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize); + + PrimitiveBatchBase(PrimitiveBatchBase&& moveFrom); + PrimitiveBatchBase& operator= (PrimitiveBatchBase&& moveFrom); + + PrimitiveBatchBase(PrimitiveBatchBase const&) = delete; + PrimitiveBatchBase& operator= (PrimitiveBatchBase const&) = delete; + + virtual ~PrimitiveBatchBase(); + + public: + // Begin/End a batch of primitive drawing operations. + void __cdecl Begin( _In_ ID3D12GraphicsCommandList* cmdList ); + void __cdecl End(); + + protected: + // Internal, untyped drawing method. + void __cdecl Draw(D3D_PRIMITIVE_TOPOLOGY topology, bool isIndexed, _In_opt_count_(indexCount) uint16_t const* indices, size_t indexCount, size_t vertexCount, _Outptr_ void** pMappedVertices); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + }; + } + + + // Template makes the API typesafe, eg. PrimitiveBatch. + template + class PrimitiveBatch : public Internal::PrimitiveBatchBase + { + static const size_t DefaultBatchSize = 4096; + + public: + explicit PrimitiveBatch(_In_ ID3D12Device* device, size_t maxIndices = DefaultBatchSize * 3, size_t maxVertices = DefaultBatchSize) + : PrimitiveBatchBase(device, maxIndices, maxVertices, sizeof(TVertex)) + { } + + PrimitiveBatch(PrimitiveBatch&& moveFrom) + : PrimitiveBatchBase(std::move(moveFrom)) + { } + + PrimitiveBatch& operator= (PrimitiveBatch&& moveFrom) + { + PrimitiveBatchBase::operator=(std::move(moveFrom)); + return *this; + } + + + // Similar to the D3D9 API DrawPrimitiveUP. + void Draw(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + { + void* mappedVertices; + + PrimitiveBatchBase::Draw(topology, false, nullptr, 0, vertexCount, &mappedVertices); + + memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); + } + + + // Similar to the D3D9 API DrawIndexedPrimitiveUP. + void DrawIndexed(D3D_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount) + { + void* mappedVertices; + + PrimitiveBatchBase::Draw(topology, true, indices, indexCount, vertexCount, &mappedVertices); + + memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex)); + } + + + void DrawLine(TVertex const& v1, TVertex const& v2) + { + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_LINELIST, false, nullptr, 0, 2, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + } + + + void DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3) + { + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, false, nullptr, 0, 3, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + mappedVertices[2] = v3; + } + + + void DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4) + { + static const uint16_t quadIndices[] = { 0, 1, 2, 0, 2, 3 }; + + TVertex* mappedVertices; + + PrimitiveBatchBase::Draw(D3D_PRIMITIVE_TOPOLOGY_QUADLIST, true, quadIndices, 6, 4, reinterpret_cast(&mappedVertices)); + + mappedVertices[0] = v1; + mappedVertices[1] = v2; + mappedVertices[2] = v3; + mappedVertices[3] = v4; + } + }; +} diff --git a/Kits/DirectXTK12/Inc/RenderTargetState.h b/Kits/DirectXTK12/Inc/RenderTargetState.h new file mode 100644 index 00000000..0e688049 --- /dev/null +++ b/Kits/DirectXTK12/Inc/RenderTargetState.h @@ -0,0 +1,77 @@ +//-------------------------------------------------------------------------------------- +// File: RenderTargetState.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +namespace DirectX +{ + // Encapsulates all render target state when creating pipeline state objects + class RenderTargetState + { + public: + RenderTargetState::RenderTargetState() + : sampleDesc{} + , rtvFormats{} + , sampleMask(~0U) + , numRenderTargets(0) + , dsvFormat(DXGI_FORMAT_UNKNOWN) + , nodeMask(0) + { + } + + RenderTargetState::RenderTargetState(const RenderTargetState& o) = default; + + // Single render target convenience constructor + RenderTargetState::RenderTargetState( + _In_ DXGI_FORMAT rtFormat, + _In_ DXGI_FORMAT dsFormat) + : sampleMask(UINT_MAX) + , sampleDesc{} + , rtvFormats{} + , numRenderTargets(1) + , dsvFormat(dsFormat) + , nodeMask(0) + { + sampleDesc.Count = 1; + rtvFormats[0] = rtFormat; + } + + // Convenience constructor converting from DXGI_SWAPCHAIN_DESC + RenderTargetState::RenderTargetState( + _In_ const DXGI_SWAP_CHAIN_DESC* desc, + _In_ DXGI_FORMAT dsFormat) + : sampleMask(UINT_MAX) + , sampleDesc{} + , rtvFormats{} + , numRenderTargets(1) + , dsvFormat(dsFormat) + , nodeMask(0) + { + rtvFormats[0] = desc->BufferDesc.Format; + sampleDesc = desc->SampleDesc; + } + + uint32_t sampleMask; + uint32_t numRenderTargets; + DXGI_FORMAT rtvFormats[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + DXGI_FORMAT dsvFormat; + DXGI_SAMPLE_DESC sampleDesc; + uint32_t nodeMask; + }; +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/ResourceUploadBatch.h b/Kits/DirectXTK12/Inc/ResourceUploadBatch.h new file mode 100644 index 00000000..2f4948f6 --- /dev/null +++ b/Kits/DirectXTK12/Inc/ResourceUploadBatch.h @@ -0,0 +1,73 @@ +//-------------------------------------------------------------------------------------- +// File: ResourceUploadBatch.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include + + +namespace DirectX +{ + // Has a command list of it's own so it can upload at any time. + class ResourceUploadBatch + { + public: + explicit ResourceUploadBatch(_In_ ID3D12Device* device); + ResourceUploadBatch(ResourceUploadBatch&& moveFrom); + ResourceUploadBatch& operator= (ResourceUploadBatch&& moveFrom); + + ResourceUploadBatch(ResourceUploadBatch const&) = delete; + ResourceUploadBatch& operator= (ResourceUploadBatch const&) = delete; + + virtual ~ResourceUploadBatch(); + + // Call this before your multiple calls to Upload. + void __cdecl Begin(); + + // Asynchronously uploads a resource. The memory in subRes is copied. + // The resource must be in the COPY_DEST state. + void __cdecl Upload( + _In_ ID3D12Resource* resource, + _In_ uint32_t subresourceIndexStart, + _In_reads_( numSubresources ) D3D12_SUBRESOURCE_DATA* subRes, + _In_ uint32_t numSubresources); + + // Asynchronously generate mips from a resource. + // Resource must be in the PIXEL_SHADER_RESOURCE state + void __cdecl GenerateMips(_In_ ID3D12Resource* resource); + + // Transition a resource once you're done with it + void __cdecl Transition( + _In_ ID3D12Resource* resource, + _In_ D3D12_RESOURCE_STATES stateBefore, + _In_ D3D12_RESOURCE_STATES stateAfter); + + // Submits all the uploads to the driver. + // No more uploads can happen after this call until Begin is called again. + // This returns a handle to an event that can be waited on. + std::future __cdecl End( + _In_ ID3D12CommandQueue* commandQueue ); + + private: + class Impl; + std::unique_ptr pImpl; + }; +} + diff --git a/Kits/DirectXTK12/Inc/ScreenGrab.h b/Kits/DirectXTK12/Inc/ScreenGrab.h new file mode 100644 index 00000000..260ae540 --- /dev/null +++ b/Kits/DirectXTK12/Inc/ScreenGrab.h @@ -0,0 +1,52 @@ +//-------------------------------------------------------------------------------------- +// File: ScreenGrab.h +// +// Function for capturing a 2D texture and saving it to a file (aka a 'screenshot' +// when used on a Direct3D Render Target). +// +// Note these functions are useful as a light-weight runtime screen grabber. For +// full-featured texture capture, DDS writer, and texture processing pipeline, +// see the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include + + +namespace DirectX +{ + // + // pSource must be in the COPY_SOURCE state before calling + // + + HRESULT __cdecl SaveDDSTextureToFile( + _In_ ID3D12CommandQueue* pCommandQueue, + _In_ ID3D12Resource* pSource, + _In_z_ const wchar_t* fileName); + + HRESULT __cdecl SaveWICTextureToFile( + _In_ ID3D12CommandQueue* pCommandQ, + _In_ ID3D12Resource* pSource, + _In_ REFGUID guidContainerFormat, + _In_z_ const wchar_t* fileName, + _In_opt_ const GUID* targetFormat = nullptr, + _In_opt_ std::function setCustomProps = nullptr); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Inc/SimpleMath.h b/Kits/DirectXTK12/Inc/SimpleMath.h new file mode 100644 index 00000000..55a0e00f --- /dev/null +++ b/Kits/DirectXTK12/Inc/SimpleMath.h @@ -0,0 +1,1020 @@ +//------------------------------------------------------------------------------------- +// SimpleMath.h -- Simplified C++ Math wrapper for DirectXMath +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#pragma once + +#if !defined(__d3d11_h__) && !defined(__d3d11_x_h__) && !defined(__d3d12_h__) && !defined(__d3d12_x_h__) +#error include d3d11.h or d3d12.h before including SimpleMath.h +#endif + +#if !defined(_XBOX_ONE) || !defined(_TITLE) +#include +#endif + +#include +#include +#include + +#include +#include +#include + +#if (defined(_XBOX_ONE) && defined(_TITLE)) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) +#include +#endif + +namespace DirectX +{ + +namespace SimpleMath +{ + +struct Vector2; +struct Vector4; +struct Matrix; +struct Quaternion; +struct Plane; + +//------------------------------------------------------------------------------ +// 2D rectangle +struct Rectangle +{ + long x; + long y; + long width; + long height; + + // Creators + Rectangle() : x(0), y(0), width(0), height(0) {} + Rectangle(long ix, long iy, long iw, long ih) : x(ix), y(iy), width(iw), height(ih) {} + explicit Rectangle(const RECT& rct) : x(rct.left), y(rct.top), width(rct.right - rct.left), height(rct.bottom - rct.top) {} + + operator RECT() { RECT rct; rct.left = x; rct.top = y; rct.right = (x + width); rct.bottom = (y + height); return rct; } +#if (defined(_XBOX_ONE) && defined(_TITLE)) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) + operator ABI::Windows::Foundation::Rect() { ABI::Windows::Foundation::Rect r; r.X = float(x); r.Y = float(y); r.Width = float(width); r.Height = float(height); return r; } +#ifdef __cplusplus_winrt + operator Windows::Foundation::Rect() { return Windows::Foundation::Rect(float(x), float(y), float(width), float(height)); } +#endif +#endif + + // Comparison operators + bool operator == (const Rectangle& r) const { return (x == r.x) && (y == r.y) && (width == r.width) && (height == r.height); } + bool operator == (const RECT& rct) const { return (x == rct.left) && (y == rct.top) && (width == (rct.right - rct.left)) && (height == (rct.bottom - rct.top)); } + + bool operator != (const Rectangle& r) const { return (x != r.x) || (y != r.y) || (width != r.width) || (height != r.height); } + bool operator != (const RECT& rct) const { return (x != rct.left) || (y != rct.top) || (width != (rct.right - rct.left)) || (height != (rct.bottom - rct.top)); } + + // Assignment operators + Rectangle& operator=(_In_ const Rectangle& r) { x = r.x; y = r.y; width = r.width; height = r.height; return *this; } + Rectangle& operator=(_In_ const RECT& rct) { x = rct.left; y = rct.top; width = (rct.right - rct.left); height = (rct.bottom - rct.top); return *this; } + + // Rectangle operations + Vector2 Location() const; + Vector2 Center() const; + + bool IsEmpty() const { return (width == 0 && height == 0 && x == 0 && y == 0); } + + bool Contains(long ix, long iy) const { return (x <= ix) && (ix < (x + width)) && (y <= iy) && (iy < (y + height)); } + bool Contains(const Vector2& point) const; + bool Contains(const Rectangle& r) const { return (x <= r.x) && ((r.x + r.width) <= (x + width)) && (y <= r.y) && ((r.y + r.height) <= (y + height)); } + bool Contains(const RECT& rct) const { return (x <= rct.left) && (rct.right <= (x + width)) && (y <= rct.top) && (rct.bottom <= (y + height)); } + + void Inflate(long horizAmount, long vertAmount); + + bool Intersects(const Rectangle& r) const { return (r.x < (x + width)) && (x < (r.x + r.width)) && (r.y < (y + height)) && (y < (r.y + r.height)); } + bool Intersects(const RECT& rct) const { return (rct.left < (x + width)) && (x < rct.right) && (rct.top < (y + height)) && (y < rct.bottom); } + + void Offset(long ox, long oy) { x += ox; y += oy; } + + // Static functions + static Rectangle Intersect(const Rectangle& ra, const Rectangle& rb); + static RECT Intersect(const RECT& rcta, const RECT& rctb); + + static Rectangle Union(const Rectangle& ra, const Rectangle& rb); + static RECT Union(const RECT& rcta, const RECT& rctb); +}; + +//------------------------------------------------------------------------------ +// 2D vector +struct Vector2 : public XMFLOAT2 +{ + Vector2() : XMFLOAT2(0.f, 0.f) {} + explicit Vector2(float x) : XMFLOAT2( x, x ) {} + Vector2(float _x, float _y) : XMFLOAT2(_x, _y) {} + explicit Vector2(_In_reads_(2) const float *pArray) : XMFLOAT2(pArray) {} + Vector2(FXMVECTOR V) { XMStoreFloat2( this, V ); } + Vector2(const XMFLOAT2& V) { this->x = V.x; this->y = V.y; } + + operator XMVECTOR() const { return XMLoadFloat2( this ); } + + // Comparison operators + bool operator == ( const Vector2& V ) const; + bool operator != ( const Vector2& V ) const; + + // Assignment operators + Vector2& operator= (const Vector2& V) { x = V.x; y = V.y; return *this; } + Vector2& operator= (const XMFLOAT2& V) { x = V.x; y = V.y; return *this; } + Vector2& operator+= (const Vector2& V); + Vector2& operator-= (const Vector2& V); + Vector2& operator*= (const Vector2& V); + Vector2& operator*= (float S); + Vector2& operator/= (float S); + + // Unary operators + Vector2 operator+ () const { return *this; } + Vector2 operator- () const { return Vector2(-x, -y); } + + // Vector operations + bool InBounds( const Vector2& Bounds ) const; + + float Length() const; + float LengthSquared() const; + + float Dot( const Vector2& V ) const; + void Cross( const Vector2& V, Vector2& result ) const; + Vector2 Cross( const Vector2& V ) const; + + void Normalize(); + void Normalize( Vector2& result ) const; + + void Clamp( const Vector2& vmin, const Vector2& vmax ); + void Clamp( const Vector2& vmin, const Vector2& vmax, Vector2& result ) const; + + // Static functions + static float Distance( const Vector2& v1, const Vector2& v2 ); + static float DistanceSquared( const Vector2& v1, const Vector2& v2 ); + + static void Min( const Vector2& v1, const Vector2& v2, Vector2& result ); + static Vector2 Min( const Vector2& v1, const Vector2& v2 ); + + static void Max( const Vector2& v1, const Vector2& v2, Vector2& result ); + static Vector2 Max( const Vector2& v1, const Vector2& v2 ); + + static void Lerp( const Vector2& v1, const Vector2& v2, float t, Vector2& result ); + static Vector2 Lerp( const Vector2& v1, const Vector2& v2, float t ); + + static void SmoothStep( const Vector2& v1, const Vector2& v2, float t, Vector2& result ); + static Vector2 SmoothStep( const Vector2& v1, const Vector2& v2, float t ); + + static void Barycentric( const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g, Vector2& result ); + static Vector2 Barycentric( const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g ); + + static void CatmullRom( const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t, Vector2& result ); + static Vector2 CatmullRom( const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t ); + + static void Hermite( const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t, Vector2& result ); + static Vector2 Hermite( const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t ); + + static void Reflect( const Vector2& ivec, const Vector2& nvec, Vector2& result ); + static Vector2 Reflect( const Vector2& ivec, const Vector2& nvec ); + + static void Refract( const Vector2& ivec, const Vector2& nvec, float refractionIndex, Vector2& result ); + static Vector2 Refract( const Vector2& ivec, const Vector2& nvec, float refractionIndex ); + + static void Transform( const Vector2& v, const Quaternion& quat, Vector2& result ); + static Vector2 Transform( const Vector2& v, const Quaternion& quat ); + + static void Transform( const Vector2& v, const Matrix& m, Vector2& result ); + static Vector2 Transform( const Vector2& v, const Matrix& m ); + static void Transform( _In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector2* resultArray ); + + static void Transform( const Vector2& v, const Matrix& m, Vector4& result ); + static void Transform( _In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector4* resultArray ); + + static void TransformNormal( const Vector2& v, const Matrix& m, Vector2& result ); + static Vector2 TransformNormal( const Vector2& v, const Matrix& m ); + static void TransformNormal( _In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector2* resultArray ); + + // Constants + static const Vector2 Zero; + static const Vector2 One; + static const Vector2 UnitX; + static const Vector2 UnitY; +}; + +// Binary operators +Vector2 operator+ (const Vector2& V1, const Vector2& V2); +Vector2 operator- (const Vector2& V1, const Vector2& V2); +Vector2 operator* (const Vector2& V1, const Vector2& V2); +Vector2 operator* (const Vector2& V, float S); +Vector2 operator/ (const Vector2& V1, const Vector2& V2); +Vector2 operator* (float S, const Vector2& V); + +//------------------------------------------------------------------------------ +// 3D vector +struct Vector3 : public XMFLOAT3 +{ + Vector3() : XMFLOAT3(0.f, 0.f, 0.f) {} + explicit Vector3(float x) : XMFLOAT3( x, x, x ) {} + Vector3(float _x, float _y, float _z) : XMFLOAT3(_x, _y, _z) {} + explicit Vector3(_In_reads_(3) const float *pArray) : XMFLOAT3(pArray) {} + Vector3(FXMVECTOR V) { XMStoreFloat3( this, V ); } + Vector3(const XMFLOAT3& V) { this->x = V.x; this->y = V.y; this->z = V.z; } + + operator XMVECTOR() const { return XMLoadFloat3( this ); } + + // Comparison operators + bool operator == ( const Vector3& V ) const; + bool operator != ( const Vector3& V ) const; + + // Assignment operators + Vector3& operator= (const Vector3& V) { x = V.x; y = V.y; z = V.z; return *this; } + Vector3& operator= (const XMFLOAT3& V) { x = V.x; y = V.y; z = V.z; return *this; } + Vector3& operator+= (const Vector3& V); + Vector3& operator-= (const Vector3& V); + Vector3& operator*= (const Vector3& V); + Vector3& operator*= (float S); + Vector3& operator/= (float S); + + // Unary operators + Vector3 operator+ () const { return *this; } + Vector3 operator- () const; + + // Vector operations + bool InBounds( const Vector3& Bounds ) const; + + float Length() const; + float LengthSquared() const; + + float Dot( const Vector3& V ) const; + void Cross( const Vector3& V, Vector3& result ) const; + Vector3 Cross( const Vector3& V ) const; + + void Normalize(); + void Normalize( Vector3& result ) const; + + void Clamp( const Vector3& vmin, const Vector3& vmax ); + void Clamp( const Vector3& vmin, const Vector3& vmax, Vector3& result ) const; + + // Static functions + static float Distance( const Vector3& v1, const Vector3& v2 ); + static float DistanceSquared( const Vector3& v1, const Vector3& v2 ); + + static void Min( const Vector3& v1, const Vector3& v2, Vector3& result ); + static Vector3 Min( const Vector3& v1, const Vector3& v2 ); + + static void Max( const Vector3& v1, const Vector3& v2, Vector3& result ); + static Vector3 Max( const Vector3& v1, const Vector3& v2 ); + + static void Lerp( const Vector3& v1, const Vector3& v2, float t, Vector3& result ); + static Vector3 Lerp( const Vector3& v1, const Vector3& v2, float t ); + + static void SmoothStep( const Vector3& v1, const Vector3& v2, float t, Vector3& result ); + static Vector3 SmoothStep( const Vector3& v1, const Vector3& v2, float t ); + + static void Barycentric( const Vector3& v1, const Vector3& v2, const Vector3& v3, float f, float g, Vector3& result ); + static Vector3 Barycentric( const Vector3& v1, const Vector3& v2, const Vector3& v3, float f, float g ); + + static void CatmullRom( const Vector3& v1, const Vector3& v2, const Vector3& v3, const Vector3& v4, float t, Vector3& result ); + static Vector3 CatmullRom( const Vector3& v1, const Vector3& v2, const Vector3& v3, const Vector3& v4, float t ); + + static void Hermite( const Vector3& v1, const Vector3& t1, const Vector3& v2, const Vector3& t2, float t, Vector3& result ); + static Vector3 Hermite( const Vector3& v1, const Vector3& t1, const Vector3& v2, const Vector3& t2, float t ); + + static void Reflect( const Vector3& ivec, const Vector3& nvec, Vector3& result ); + static Vector3 Reflect( const Vector3& ivec, const Vector3& nvec ); + + static void Refract( const Vector3& ivec, const Vector3& nvec, float refractionIndex, Vector3& result ); + static Vector3 Refract( const Vector3& ivec, const Vector3& nvec, float refractionIndex ); + + static void Transform( const Vector3& v, const Quaternion& quat, Vector3& result ); + static Vector3 Transform( const Vector3& v, const Quaternion& quat ); + + static void Transform( const Vector3& v, const Matrix& m, Vector3& result ); + static Vector3 Transform( const Vector3& v, const Matrix& m ); + static void Transform( _In_reads_(count) const Vector3* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector3* resultArray ); + + static void Transform( const Vector3& v, const Matrix& m, Vector4& result ); + static void Transform( _In_reads_(count) const Vector3* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector4* resultArray ); + + static void TransformNormal( const Vector3& v, const Matrix& m, Vector3& result ); + static Vector3 TransformNormal( const Vector3& v, const Matrix& m ); + static void TransformNormal( _In_reads_(count) const Vector3* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector3* resultArray ); + + // Constants + static const Vector3 Zero; + static const Vector3 One; + static const Vector3 UnitX; + static const Vector3 UnitY; + static const Vector3 UnitZ; + static const Vector3 Up; + static const Vector3 Down; + static const Vector3 Right; + static const Vector3 Left; + static const Vector3 Forward; + static const Vector3 Backward; +}; + +// Binary operators +Vector3 operator+ (const Vector3& V1, const Vector3& V2); +Vector3 operator- (const Vector3& V1, const Vector3& V2); +Vector3 operator* (const Vector3& V1, const Vector3& V2); +Vector3 operator* (const Vector3& V, float S); +Vector3 operator/ (const Vector3& V1, const Vector3& V2); +Vector3 operator* (float S, const Vector3& V); + +//------------------------------------------------------------------------------ +// 4D vector +struct Vector4 : public XMFLOAT4 +{ + Vector4() : XMFLOAT4(0.f, 0.f, 0.f, 0.f) {} + explicit Vector4(float x) : XMFLOAT4( x, x, x, x ) {} + Vector4(float _x, float _y, float _z, float _w) : XMFLOAT4(_x, _y, _z, _w) {} + explicit Vector4(_In_reads_(4) const float *pArray) : XMFLOAT4(pArray) {} + Vector4(FXMVECTOR V) { XMStoreFloat4( this, V ); } + Vector4(const XMFLOAT4& V) { this->x = V.x; this->y = V.y; this->z = V.z; this->w = V.w; } + + operator XMVECTOR() const { return XMLoadFloat4( this ); } + + // Comparison operators + bool operator == ( const Vector4& V ) const; + bool operator != ( const Vector4& V ) const; + + // Assignment operators + Vector4& operator= (const Vector4& V) { x = V.x; y = V.y; z = V.z; w = V.w; return *this; } + Vector4& operator= (const XMFLOAT4& V) { x = V.x; y = V.y; z = V.z; w = V.w; return *this; } + Vector4& operator+= (const Vector4& V); + Vector4& operator-= (const Vector4& V); + Vector4& operator*= (const Vector4& V); + Vector4& operator*= (float S); + Vector4& operator/= (float S); + + // Unary operators + Vector4 operator+ () const { return *this; } + Vector4 operator- () const; + + // Vector operations + bool InBounds( const Vector4& Bounds ) const; + + float Length() const; + float LengthSquared() const; + + float Dot( const Vector4& V ) const; + void Cross( const Vector4& v1, const Vector4& v2, Vector4& result ) const; + Vector4 Cross( const Vector4& v1, const Vector4& v2 ) const; + + void Normalize(); + void Normalize( Vector4& result ) const; + + void Clamp( const Vector4& vmin, const Vector4& vmax ); + void Clamp( const Vector4& vmin, const Vector4& vmax, Vector4& result ) const; + + // Static functions + static float Distance( const Vector4& v1, const Vector4& v2 ); + static float DistanceSquared( const Vector4& v1, const Vector4& v2 ); + + static void Min( const Vector4& v1, const Vector4& v2, Vector4& result ); + static Vector4 Min( const Vector4& v1, const Vector4& v2 ); + + static void Max( const Vector4& v1, const Vector4& v2, Vector4& result ); + static Vector4 Max( const Vector4& v1, const Vector4& v2 ); + + static void Lerp( const Vector4& v1, const Vector4& v2, float t, Vector4& result ); + static Vector4 Lerp( const Vector4& v1, const Vector4& v2, float t ); + + static void SmoothStep( const Vector4& v1, const Vector4& v2, float t, Vector4& result ); + static Vector4 SmoothStep( const Vector4& v1, const Vector4& v2, float t ); + + static void Barycentric( const Vector4& v1, const Vector4& v2, const Vector4& v3, float f, float g, Vector4& result ); + static Vector4 Barycentric( const Vector4& v1, const Vector4& v2, const Vector4& v3, float f, float g ); + + static void CatmullRom( const Vector4& v1, const Vector4& v2, const Vector4& v3, const Vector4& v4, float t, Vector4& result ); + static Vector4 CatmullRom( const Vector4& v1, const Vector4& v2, const Vector4& v3, const Vector4& v4, float t ); + + static void Hermite( const Vector4& v1, const Vector4& t1, const Vector4& v2, const Vector4& t2, float t, Vector4& result ); + static Vector4 Hermite( const Vector4& v1, const Vector4& t1, const Vector4& v2, const Vector4& t2, float t ); + + static void Reflect( const Vector4& ivec, const Vector4& nvec, Vector4& result ); + static Vector4 Reflect( const Vector4& ivec, const Vector4& nvec ); + + static void Refract( const Vector4& ivec, const Vector4& nvec, float refractionIndex, Vector4& result ); + static Vector4 Refract( const Vector4& ivec, const Vector4& nvec, float refractionIndex ); + + static void Transform( const Vector2& v, const Quaternion& quat, Vector4& result ); + static Vector4 Transform( const Vector2& v, const Quaternion& quat ); + + static void Transform( const Vector3& v, const Quaternion& quat, Vector4& result ); + static Vector4 Transform( const Vector3& v, const Quaternion& quat ); + + static void Transform( const Vector4& v, const Quaternion& quat, Vector4& result ); + static Vector4 Transform( const Vector4& v, const Quaternion& quat ); + + static void Transform( const Vector4& v, const Matrix& m, Vector4& result ); + static Vector4 Transform( const Vector4& v, const Matrix& m ); + static void Transform( _In_reads_(count) const Vector4* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector4* resultArray ); + + // Constants + static const Vector4 Zero; + static const Vector4 One; + static const Vector4 UnitX; + static const Vector4 UnitY; + static const Vector4 UnitZ; + static const Vector4 UnitW; +}; + +// Binary operators +Vector4 operator+ (const Vector4& V1, const Vector4& V2); +Vector4 operator- (const Vector4& V1, const Vector4& V2); +Vector4 operator* (const Vector4& V1, const Vector4& V2); +Vector4 operator* (const Vector4& V, float S); +Vector4 operator/ (const Vector4& V1, const Vector4& V2); +Vector4 operator* (float S, const Vector4& V); + +//------------------------------------------------------------------------------ +// 4x4 Matrix (assumes right-handed cooordinates) +struct Matrix : public XMFLOAT4X4 +{ + Matrix() : XMFLOAT4X4( 1.f, 0, 0, 0, + 0, 1.f, 0, 0, + 0, 0, 1.f, 0, + 0, 0, 0, 1.f ) {} + Matrix(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) : XMFLOAT4X4(m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33) {} + explicit Matrix( const Vector3& r0, const Vector3& r1, const Vector3& r2 ) : XMFLOAT4X4( r0.x, r0.y, r0.z, 0, + r1.x, r1.y, r1.z, 0, + r2.x, r2.y, r2.z, 0, + 0, 0, 0, 1.f ) {} + explicit Matrix( const Vector4& r0, const Vector4& r1, const Vector4& r2, const Vector4& r3 ) : XMFLOAT4X4( r0.x, r0.y, r0.z, r0.w, + r1.x, r1.y, r1.z, r1.w, + r2.x, r2.y, r2.z, r2.w, + r3.x, r3.y, r3.z, r3.w ) {} + Matrix(const XMFLOAT4X4& M) { memcpy_s(this, sizeof(float)*16, &M, sizeof(XMFLOAT4X4)); } + Matrix(const XMFLOAT3X3& M); + Matrix(const XMFLOAT4X3& M); + + explicit Matrix(_In_reads_(16) const float *pArray) : XMFLOAT4X4(pArray) {} + Matrix( CXMMATRIX M ) { XMStoreFloat4x4( this, M ); } + + operator XMMATRIX() const { return XMLoadFloat4x4( this ); } + + // Comparison operators + bool operator == ( const Matrix& M ) const; + bool operator != ( const Matrix& M ) const; + + // Assignment operators + Matrix& operator= (const Matrix& M) { memcpy_s( this, sizeof(float)*16, &M, sizeof(float)*16 ); return *this; } + Matrix& operator= (const XMFLOAT4X4& M) { memcpy_s( this, sizeof(float)*16, &M, sizeof(XMFLOAT4X4) ); return *this; } + Matrix& operator= (const XMFLOAT3X3& M); + Matrix& operator= (const XMFLOAT4X3& M); + Matrix& operator+= (const Matrix& M); + Matrix& operator-= (const Matrix& M); + Matrix& operator*= (const Matrix& M); + Matrix& operator*= (float S); + Matrix& operator/= (float S); + + Matrix& operator/= (const Matrix& M); + // Element-wise divide + + // Unary operators + Matrix operator+ () const { return *this; } + Matrix operator- () const; + + // Properties + Vector3 Up() const { return Vector3( _21, _22, _23); } + void Up( const Vector3& v ) { _21 = v.x; _22 = v.y; _23 = v.z; } + + Vector3 Down() const { return Vector3( -_21, -_22, -_23); } + void Down( const Vector3& v ) { _21 = -v.x; _22 = -v.y; _23 = -v.z; } + + Vector3 Right() const { return Vector3( _11, _12, _13 ); } + void Right( const Vector3& v ) { _11 = v.x; _12 = v.y; _13 = v.z; } + + Vector3 Left() const { return Vector3( -_11, -_12, -_13 ); } + void Left( const Vector3& v ) { _11 = -v.x; _12 = -v.y; _13 = -v.z; } + + Vector3 Forward() const { return Vector3( -_31, -_32, -_33 ); } + void Forward( const Vector3& v ) { _31 = -v.x; _32 = -v.y; _33 = -v.z; } + + Vector3 Backward() const { return Vector3( _31, _32, _33 ); } + void Backward( const Vector3& v ) { _31 = v.x; _32 = v.y; _33 = v.z; } + + Vector3 Translation() const { return Vector3( _41, _42, _43 ); } + void Translation( const Vector3& v ) { _41 = v.x; _42 = v.y; _43 = v.z; } + + // Matrix operations + bool Decompose( Vector3& scale, Quaternion& rotation, Vector3& translation ); + + Matrix Transpose() const; + void Transpose( Matrix& result ) const; + + Matrix Invert() const; + void Invert( Matrix& result ) const; + + float Determinant() const; + + // Static functions + static Matrix CreateBillboard( const Vector3& object, const Vector3& cameraPosition, const Vector3& cameraUp, _In_opt_ const Vector3* cameraForward = nullptr ); + + static Matrix CreateConstrainedBillboard( const Vector3& object, const Vector3& cameraPosition, const Vector3& rotateAxis, + _In_opt_ const Vector3* cameraForward = nullptr, _In_opt_ const Vector3* objectForward = nullptr); + + static Matrix CreateTranslation( const Vector3& position ); + static Matrix CreateTranslation( float x, float y, float z ); + + static Matrix CreateScale( const Vector3& scales ); + static Matrix CreateScale( float xs, float ys, float zs ); + static Matrix CreateScale( float scale ); + + static Matrix CreateRotationX( float radians ); + static Matrix CreateRotationY( float radians ); + static Matrix CreateRotationZ( float radians ); + + static Matrix CreateFromAxisAngle( const Vector3& axis, float angle ); + + static Matrix CreatePerspectiveFieldOfView( float fov, float aspectRatio, float nearPlane, float farPlane ); + static Matrix CreatePerspective( float width, float height, float nearPlane, float farPlane ); + static Matrix CreatePerspectiveOffCenter( float left, float right, float bottom, float top, float nearPlane, float farPlane ); + static Matrix CreateOrthographic( float width, float height, float zNearPlane, float zFarPlane ); + static Matrix CreateOrthographicOffCenter( float left, float right, float bottom, float top, float zNearPlane, float zFarPlane ); + + static Matrix CreateLookAt( const Vector3& position, const Vector3& target, const Vector3& up ); + static Matrix CreateWorld( const Vector3& position, const Vector3& forward, const Vector3& up ); + + static Matrix CreateFromQuaternion( const Quaternion& quat ); + + static Matrix CreateFromYawPitchRoll( float yaw, float pitch, float roll ); + + static Matrix CreateShadow( const Vector3& lightDir, const Plane& plane ); + + static Matrix CreateReflection( const Plane& plane ); + + static void Lerp( const Matrix& M1, const Matrix& M2, float t, Matrix& result ); + static Matrix Lerp( const Matrix& M1, const Matrix& M2, float t ); + + static void Transform( const Matrix& M, const Quaternion& rotation, Matrix& result ); + static Matrix Transform( const Matrix& M, const Quaternion& rotation ); + + // Constants + static const Matrix Identity; +}; + +// Binary operators +Matrix operator+ (const Matrix& M1, const Matrix& M2); +Matrix operator- (const Matrix& M1, const Matrix& M2); +Matrix operator* (const Matrix& M1, const Matrix& M2); +Matrix operator* (const Matrix& M, float S); +Matrix operator/ (const Matrix& M, float S); +Matrix operator/ (const Matrix& M1, const Matrix& M2); + // Element-wise divide +Matrix operator* (float S, const Matrix& M); + + +//----------------------------------------------------------------------------- +// Plane +struct Plane : public XMFLOAT4 +{ + Plane() : XMFLOAT4(0.f, 1.f, 0.f, 0.f) {} + Plane(float _x, float _y, float _z, float _w) : XMFLOAT4(_x, _y, _z, _w) {} + Plane(const Vector3& normal, float d) : XMFLOAT4(normal.x, normal.y, normal.z, d) {} + Plane(const Vector3& point1, const Vector3& point2, const Vector3& point3 ); + Plane(const Vector3& point, const Vector3& normal); + explicit Plane(const Vector4& v) : XMFLOAT4(v.x, v.y, v.z, v.w) {} + explicit Plane(_In_reads_(4) const float *pArray) : XMFLOAT4(pArray) {} + Plane(FXMVECTOR V) { XMStoreFloat4( this, V ); } + Plane(const XMFLOAT4& p) { this->x = p.x; this->y = p.y; this->z = p.z; this->w = p.w; } + + operator XMVECTOR() const { return XMLoadFloat4( this ); } + + // Comparison operators + bool operator == ( const Plane& p ) const; + bool operator != ( const Plane& p ) const; + + // Assignment operators + Plane& operator= (const Plane& p) { x = p.x; y = p.y; z = p.z; w = p.w; return *this; } + Plane& operator= (const XMFLOAT4& p) { x = p.x; y = p.y; z = p.z; w = p.w; return *this; } + + // Properties + Vector3 Normal() const { return Vector3( x, y, z ); } + void Normal( const Vector3& normal ) { x = normal.x; y = normal.y; z = normal.z; } + + float D() const { return w; } + void D(float d) { w = d; } + + // Plane operations + void Normalize(); + void Normalize( Plane& result ) const; + + float Dot( const Vector4& v ) const; + float DotCoordinate( const Vector3& position ) const; + float DotNormal( const Vector3& normal ) const; + + // Static functions + static void Transform( const Plane& plane, const Matrix& M, Plane& result ); + static Plane Transform( const Plane& plane, const Matrix& M ); + + static void Transform( const Plane& plane, const Quaternion& rotation, Plane& result ); + static Plane Transform( const Plane& plane, const Quaternion& rotation ); + // Input quaternion must be the inverse transpose of the transformation +}; + +//------------------------------------------------------------------------------ +// Quaternion +struct Quaternion : public XMFLOAT4 +{ + Quaternion() : XMFLOAT4(0, 0, 0, 1.f) {} + Quaternion( float _x, float _y, float _z, float _w ) : XMFLOAT4(_x, _y, _z, _w) {} + Quaternion( const Vector3& v, float scalar ) : XMFLOAT4( v.x, v.y, v.z, scalar ) {} + explicit Quaternion( const Vector4& v ) : XMFLOAT4( v.x, v.y, v.z, v.w ) {} + explicit Quaternion(_In_reads_(4) const float *pArray) : XMFLOAT4(pArray) {} + Quaternion(FXMVECTOR V) { XMStoreFloat4( this, V ); } + Quaternion(const XMFLOAT4& q) { this->x = q.x; this->y = q.y; this->z = q.z; this->w = q.w; } + + operator XMVECTOR() const { return XMLoadFloat4( this ); } + + // Comparison operators + bool operator == ( const Quaternion& q ) const; + bool operator != ( const Quaternion& q ) const; + + // Assignment operators + Quaternion& operator= (const Quaternion& q) { x = q.x; y = q.y; z = q.z; w = q.w; return *this; } + Quaternion& operator= (const XMFLOAT4& q) { x = q.x; y = q.y; z = q.z; w = q.w; return *this; } + Quaternion& operator+= (const Quaternion& q); + Quaternion& operator-= (const Quaternion& q); + Quaternion& operator*= (const Quaternion& q); + Quaternion& operator*= (float S); + Quaternion& operator/= (const Quaternion& q); + + // Unary operators + Quaternion operator+ () const { return *this; } + Quaternion operator- () const; + + // Quaternion operations + float Length() const; + float LengthSquared() const; + + void Normalize(); + void Normalize( Quaternion& result ) const; + + void Conjugate(); + void Conjugate( Quaternion& result ) const; + + void Inverse( Quaternion& result ) const; + + float Dot( const Quaternion& Q ) const; + + // Static functions + static Quaternion CreateFromAxisAngle( const Vector3& axis, float angle ); + static Quaternion CreateFromYawPitchRoll( float yaw, float pitch, float roll ); + static Quaternion CreateFromRotationMatrix( const Matrix& M ); + + static void Lerp( const Quaternion& q1, const Quaternion& q2, float t, Quaternion& result ); + static Quaternion Lerp( const Quaternion& q1, const Quaternion& q2, float t ); + + static void Slerp( const Quaternion& q1, const Quaternion& q2, float t, Quaternion& result ); + static Quaternion Slerp( const Quaternion& q1, const Quaternion& q2, float t ); + + static void Concatenate( const Quaternion& q1, const Quaternion& q2, Quaternion& result ); + static Quaternion Concatenate( const Quaternion& q1, const Quaternion& q2 ); + + // Constants + static const Quaternion Identity; +}; + +// Binary operators +Quaternion operator+ (const Quaternion& Q1, const Quaternion& Q2); +Quaternion operator- (const Quaternion& Q1, const Quaternion& Q2); +Quaternion operator* (const Quaternion& Q1, const Quaternion& Q2); +Quaternion operator* (const Quaternion& Q, float S); +Quaternion operator/ (const Quaternion& Q1, const Quaternion& Q2); +Quaternion operator* (float S, const Quaternion& Q); + +//------------------------------------------------------------------------------ +// Color +struct Color : public XMFLOAT4 +{ + Color() : XMFLOAT4(0, 0, 0, 1.f) {} + Color( float _r, float _g, float _b ) : XMFLOAT4(_r, _g, _b, 1.f) {} + Color( float _r, float _g, float _b, float _a ) : XMFLOAT4(_r, _g, _b, _a) {} + explicit Color( const Vector3& clr ) : XMFLOAT4( clr.x, clr.y, clr.z, 1.f ) {} + explicit Color( const Vector4& clr ) : XMFLOAT4( clr.x, clr.y, clr.z, clr.w ) {} + explicit Color(_In_reads_(4) const float *pArray) : XMFLOAT4(pArray) {} + Color(FXMVECTOR V) { XMStoreFloat4( this, V ); } + Color(const XMFLOAT4& c) { this->x = c.x; this->y = c.y; this->z = c.z; this->w = c.w; } + + explicit Color( const DirectX::PackedVector::XMCOLOR& Packed ); + // BGRA Direct3D 9 D3DCOLOR packed color + + explicit Color( const DirectX::PackedVector::XMUBYTEN4& Packed ); + // RGBA XNA Game Studio packed color + + operator XMVECTOR() const { return XMLoadFloat4( this ); } + operator const float*() const { return reinterpret_cast(this); } + + // Comparison operators + bool operator == ( const Color& c ) const; + bool operator != ( const Color& c ) const; + + // Assignment operators + Color& operator= (const Color& c) { x = c.x; y = c.y; z = c.z; w = c.w; return *this; } + Color& operator= (const XMFLOAT4& c) { x = c.x; y = c.y; z = c.z; w = c.w; return *this; } + Color& operator= (const DirectX::PackedVector::XMCOLOR& Packed); + Color& operator= (const DirectX::PackedVector::XMUBYTEN4& Packed); + Color& operator+= (const Color& c); + Color& operator-= (const Color& c); + Color& operator*= (const Color& c); + Color& operator*= (float S); + Color& operator/= (const Color& c); + + // Unary operators + Color operator+ () const { return *this; } + Color operator- () const; + + // Properties + float R() const { return x; } + void R(float r) { x = r; } + + float G() const { return y; } + void G(float g) { y = g; } + + float B() const { return z; } + void B(float b) { z = b; } + + float A() const { return w; } + void A(float a) { w = a; } + + // Color operations + DirectX::PackedVector::XMCOLOR BGRA() const; + DirectX::PackedVector::XMUBYTEN4 RGBA() const; + + Vector3 ToVector3() const; + Vector4 ToVector4() const; + + void Negate(); + void Negate( Color& result ) const; + + void Saturate(); + void Saturate( Color& result ) const; + + void Premultiply(); + void Premultiply( Color& result ) const; + + void AdjustSaturation( float sat ); + void AdjustSaturation( float sat, Color& result ) const; + + void AdjustContrast( float contrast ); + void AdjustContrast( float contrast, Color& result ) const; + + // Static functions + static void Modulate( const Color& c1, const Color& c2, Color& result ); + static Color Modulate( const Color& c1, const Color& c2 ); + + static void Lerp( const Color& c1, const Color& c2, float t, Color& result ); + static Color Lerp( const Color& c1, const Color& c2, float t ); +}; + +// Binary operators +Color operator+ (const Color& C1, const Color& C2); +Color operator- (const Color& C1, const Color& C2); +Color operator* (const Color& C1, const Color& C2); +Color operator* (const Color& C, float S); +Color operator/ (const Color& C1, const Color& C2); +Color operator* (float S, const Color& C); + +//------------------------------------------------------------------------------ +// Ray +class Ray +{ +public: + Vector3 position; + Vector3 direction; + + Ray() : position(0,0,0), direction(0,0,1) {} + Ray( const Vector3& pos, const Vector3& dir ) : position(pos), direction(dir) {} + + // Comparison operators + bool operator == ( const Ray& r ) const; + bool operator != ( const Ray& r ) const; + + // Ray operations + bool Intersects( const BoundingSphere& sphere, _Out_ float& Dist ) const; + bool Intersects( const BoundingBox& box, _Out_ float& Dist ) const; + bool Intersects( const Vector3& tri0, const Vector3& tri1, const Vector3& tri2, _Out_ float& Dist ) const; + bool Intersects( const Plane& plane, _Out_ float& Dist ) const; +}; + +//------------------------------------------------------------------------------ +// Viewport +class Viewport +{ +public: + float x; + float y; + float width; + float height; + float minDepth; + float maxDepth; + + Viewport() : + x(0.f), y(0.f), width(0.f), height(0.f), minDepth(0.f), maxDepth(1.f) {} + Viewport( float ix, float iy, float iw, float ih, float iminz = 0.f, float imaxz = 1.f ) : + x(ix), y(iy), width(iw), height(ih), minDepth(iminz), maxDepth(imaxz) {} + explicit Viewport(const RECT& rct) : + x(float(rct.left)), y(float(rct.top)), + width(float(rct.right - rct.left)), + height(float(rct.bottom - rct.top)), + minDepth(0.f), maxDepth(1.f) {} + +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) + // Direct3D 11 interop + explicit Viewport(const D3D11_VIEWPORT& vp) : + x(vp.TopLeftX), y(vp.TopLeftY), + width(vp.Width), height(vp.Height), + minDepth(vp.MinDepth), maxDepth(vp.MaxDepth) {} + + operator D3D11_VIEWPORT() { return *reinterpret_cast(this); } + const D3D11_VIEWPORT* Get11() const { return reinterpret_cast(this); } + Viewport& operator= (const D3D11_VIEWPORT& vp); +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) + // Direct3D 12 interop + explicit Viewport(const D3D12_VIEWPORT& vp) : + x(vp.TopLeftX), y(vp.TopLeftY), + width(vp.Width), height(vp.Height), + minDepth(vp.MinDepth), maxDepth(vp.MaxDepth) {} + + operator D3D12_VIEWPORT() { return *reinterpret_cast(this); } + const D3D12_VIEWPORT* Get12() const { return reinterpret_cast(this); } + Viewport& operator= (const D3D12_VIEWPORT& vp); +#endif + + // Comparison operators + bool operator == ( const Viewport& vp ) const; + bool operator != ( const Viewport& vp ) const; + + // Assignment operators + Viewport& operator= (const Viewport& vp); + Viewport& operator= (const RECT& rct); + + // Viewport operations + float AspectRatio() const; + + Vector3 Project(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world ) const; + void Project(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world, Vector3& result ) const; + + Vector3 Unproject(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world ) const; + void Unproject(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world, Vector3& result ) const; + + // Static methods + static RECT __cdecl ComputeDisplayArea(DXGI_SCALING scaling, UINT backBufferWidth, UINT backBufferHeight, int outputWidth, int outputHeight); + static RECT __cdecl ComputeTitleSafeArea(UINT backBufferWidth, UINT backBufferHeight); +}; + +#include "SimpleMath.inl" + +}; // namespace SimpleMath + +}; // namespace DirectX + +//------------------------------------------------------------------------------ +// Support for SimpleMath and Standard C++ Library containers +namespace std +{ + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Rectangle& r1, const DirectX::SimpleMath::Rectangle& r2) const + { + return ((r1.x < r2.x) + || ((r1.x == r2.x) && (r1.y < r2.y)) + || ((r1.x == r2.x) && (r1.y == r2.y) && (r1.width < r2.width)) + || ((r1.x == r2.x) && (r1.y == r2.y) && (r1.width == r2.width) && (r1.height < r2.height))); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Vector2& V1, const DirectX::SimpleMath::Vector2& V2) const + { + return ( (V1.x < V2.x) || ((V1.x == V2.x) && (V1.y < V2.y)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Vector3& V1, const DirectX::SimpleMath::Vector3& V2) const + { + return ( (V1.x < V2.x) + || ((V1.x == V2.x) && (V1.y < V2.y)) + || ((V1.x == V2.x) && (V1.y == V2.y) && (V1.z < V2.z)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Vector4& V1, const DirectX::SimpleMath::Vector4& V2) const + { + return ( (V1.x < V2.x) + || ((V1.x == V2.x) && (V1.y < V2.y)) + || ((V1.x == V2.x) && (V1.y == V2.y) && (V1.z < V2.z)) + || ((V1.x == V2.x) && (V1.y == V2.y) && (V1.z == V2.z) && (V1.w < V2.w)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Matrix& M1, const DirectX::SimpleMath::Matrix& M2) const + { + if (M1._11 != M2._11) return M1._11 < M2._11; + if (M1._12 != M2._12) return M1._12 < M2._12; + if (M1._13 != M2._13) return M1._13 < M2._13; + if (M1._14 != M2._14) return M1._14 < M2._14; + if (M1._21 != M2._21) return M1._21 < M2._21; + if (M1._22 != M2._22) return M1._22 < M2._22; + if (M1._23 != M2._23) return M1._23 < M2._23; + if (M1._24 != M2._24) return M1._24 < M2._24; + if (M1._31 != M2._31) return M1._31 < M2._31; + if (M1._32 != M2._32) return M1._32 < M2._32; + if (M1._33 != M2._33) return M1._33 < M2._33; + if (M1._34 != M2._34) return M1._34 < M2._34; + if (M1._41 != M2._41) return M1._41 < M2._41; + if (M1._42 != M2._42) return M1._42 < M2._42; + if (M1._43 != M2._43) return M1._43 < M2._43; + if (M1._44 != M2._44) return M1._44 < M2._44; + + return false; + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Plane& P1, const DirectX::SimpleMath::Plane& P2) const + { + return ( (P1.x < P2.x) + || ((P1.x == P2.x) && (P1.y < P2.y)) + || ((P1.x == P2.x) && (P1.y == P2.y) && (P1.z < P2.z)) + || ((P1.x == P2.x) && (P1.y == P2.y) && (P1.z == P2.z) && (P1.w < P2.w)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Quaternion& Q1, const DirectX::SimpleMath::Quaternion& Q2) const + { + return ( (Q1.x < Q2.x) + || ((Q1.x == Q2.x) && (Q1.y < Q2.y)) + || ((Q1.x == Q2.x) && (Q1.y == Q2.y) && (Q1.z < Q2.z)) + || ((Q1.x == Q2.x) && (Q1.y == Q2.y) && (Q1.z == Q2.z) && (Q1.w < Q2.w)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Color& C1, const DirectX::SimpleMath::Color& C2) const + { + return ( (C1.x < C2.x) + || ((C1.x == C2.x) && (C1.y < C2.y)) + || ((C1.x == C2.x) && (C1.y == C2.y) && (C1.z < C2.z)) + || ((C1.x == C2.x) && (C1.y == C2.y) && (C1.z == C2.z) && (C1.w < C2.w)) ); + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Ray& R1, const DirectX::SimpleMath::Ray& R2) const + { + if (R1.position.x != R2.position.x) return R1.position.x < R2.position.x; + if (R1.position.y != R2.position.y) return R1.position.y < R2.position.y; + if (R1.position.z != R2.position.z) return R1.position.z < R2.position.z; + + if (R1.direction.x != R2.direction.x) return R1.direction.x < R2.direction.x; + if (R1.direction.y != R2.direction.y) return R1.direction.y < R2.direction.y; + if (R1.direction.z != R2.direction.z) return R1.direction.z < R2.direction.z; + + return false; + } + }; + + template<> struct less + { + bool operator()(const DirectX::SimpleMath::Viewport& vp1, const DirectX::SimpleMath::Viewport& vp2) const + { + if (vp1.x != vp2.x) return (vp1.x < vp2.x); + if (vp1.y != vp2.y) return (vp1.y < vp2.y); + + if (vp1.width != vp2.width) return (vp1.width < vp2.width); + if (vp1.height != vp2.height) return (vp1.height < vp2.height); + + if (vp1.minDepth != vp2.minDepth) return (vp1.minDepth < vp2.minDepth); + if (vp1.maxDepth != vp2.maxDepth) return (vp1.maxDepth < vp2.maxDepth); + + return false; + } + }; + +} // namespace std diff --git a/Kits/DirectXTK12/Inc/SimpleMath.inl b/Kits/DirectXTK12/Inc/SimpleMath.inl new file mode 100644 index 00000000..1be0a5fc --- /dev/null +++ b/Kits/DirectXTK12/Inc/SimpleMath.inl @@ -0,0 +1,3706 @@ +//------------------------------------------------------------------------------------- +// SimpleMath.inl -- Simplified C++ Math wrapper for DirectXMath +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#pragma once + +/**************************************************************************** +* +* Rectangle +* +****************************************************************************/ + +//------------------------------------------------------------------------------ +// Rectangle operations +//------------------------------------------------------------------------------ +inline Vector2 Rectangle::Location() const +{ + return Vector2(float(x), float(y)); +} + +inline Vector2 Rectangle::Center() const +{ + return Vector2(float(x) + float(width / 2.f), float(y) + float(height / 2.f)); +} + +inline bool Rectangle::Contains(const Vector2& point) const +{ + return (float(x) <= point.x) && (point.x < float(x + width)) && (float(y) <= point.y) && (point.y < float(y + height)); +} + +inline void Rectangle::Inflate(long horizAmount, long vertAmount) +{ + x -= horizAmount; + y -= vertAmount; + width += horizAmount; + height += vertAmount; +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline Rectangle Rectangle::Intersect(const Rectangle& ra, const Rectangle& rb) +{ + long righta = ra.x + ra.width; + long rightb = rb.x + rb.width; + + long bottoma = ra.y + ra.height; + long bottomb = rb.y + rb.height; + + long maxX = ra.x > rb.x ? ra.x : rb.x; + long maxY = ra.y > rb.y ? ra.y : rb.y; + + long minRight = righta < rightb ? righta : rightb; + long minBottom = bottoma < bottomb ? bottoma : bottomb; + + Rectangle result; + + if ((minRight > maxX) && (minBottom > maxY)) + { + result.x = maxX; + result.y = maxY; + result.width = minRight - maxX; + result.height = minBottom - maxY; + } + else + { + result.x = 0; + result.y = 0; + result.width = 0; + result.height = 0; + } + + return result; +} + +inline RECT Rectangle::Intersect(const RECT& rcta, const RECT& rctb) +{ + long maxX = rcta.left > rctb.left ? rcta.left : rctb.left; + long maxY = rcta.top > rctb.top ? rcta.top : rctb.top; + + long minRight = rcta.right < rctb.right ? rcta.right : rctb.right; + long minBottom = rcta.bottom < rctb.bottom ? rcta.bottom : rctb.bottom; + + RECT result; + + if ((minRight > maxX) && (minBottom > maxY)) + { + result.left = maxX; + result.top = maxY; + result.right = minRight; + result.bottom = minBottom; + } + else + { + result.left = 0; + result.top = 0; + result.right = 0; + result.bottom = 0; + } + + return result; +} + +inline Rectangle Rectangle::Union(const Rectangle& ra, const Rectangle& rb) +{ + long righta = ra.x + ra.width; + long rightb = rb.x + rb.width; + + long bottoma = ra.y + ra.height; + long bottomb = rb.y + rb.height; + + int minX = ra.x < rb.x ? ra.x : rb.x; + int minY = ra.y < rb.y ? ra.y : rb.y; + + int maxRight = righta > rightb ? righta : rightb; + int maxBottom = bottoma > bottomb ? bottoma : bottomb; + + Rectangle result; + result.x = minX; + result.y = minY; + result.width = maxRight - minX; + result.height = maxBottom - minY; + return result; +} + +inline RECT Rectangle::Union(const RECT& rcta, const RECT& rctb) +{ + RECT result; + result.left = rcta.left < rctb.left ? rcta.left : rctb.left; + result.top = rcta.top < rctb.top ? rcta.top : rctb.top; + result.right = rcta.right > rctb.right ? rcta.right : rctb.right; + result.bottom = rcta.bottom > rctb.bottom ? rcta.bottom : rctb.bottom; + return result; +} + + +/**************************************************************************** + * + * Vector2 + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Vector2::operator == ( const Vector2& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + return XMVector2Equal( v1, v2 ); +} + +inline bool Vector2::operator != ( const Vector2& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + return XMVector2NotEqual( v1, v2 ); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Vector2& Vector2::operator+= (const Vector2& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR X = XMVectorAdd(v1,v2); + XMStoreFloat2( this, X ); + return *this; +} + +inline Vector2& Vector2::operator-= (const Vector2& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR X = XMVectorSubtract(v1,v2); + XMStoreFloat2( this, X ); + return *this; +} + +inline Vector2& Vector2::operator*= (const Vector2& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR X = XMVectorMultiply(v1,v2); + XMStoreFloat2( this, X ); + return *this; +} + +inline Vector2& Vector2::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVectorScale(v1,S); + XMStoreFloat2( this, X ); + return *this; +} + +inline Vector2& Vector2::operator/= (float S) +{ + using namespace DirectX; + assert( S != 0.0f ); + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVectorScale(v1, 1.f/S); + XMStoreFloat2( this, X ); + return *this; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Vector2 operator+ (const Vector2& V1, const Vector2& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V1 ); + XMVECTOR v2 = XMLoadFloat2( &V2 ); + XMVECTOR X = XMVectorAdd(v1,v2); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +inline Vector2 operator- (const Vector2& V1, const Vector2& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V1 ); + XMVECTOR v2 = XMLoadFloat2( &V2 ); + XMVECTOR X = XMVectorSubtract(v1,v2); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +inline Vector2 operator* (const Vector2& V1, const Vector2& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V1 ); + XMVECTOR v2 = XMLoadFloat2( &V2 ); + XMVECTOR X = XMVectorMultiply(v1,v2); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +inline Vector2 operator* (const Vector2& V, float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +inline Vector2 operator/ (const Vector2& V1, const Vector2& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V1 ); + XMVECTOR v2 = XMLoadFloat2( &V2 ); + XMVECTOR X = XMVectorDivide(v1,v2); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +inline Vector2 operator* (float S, const Vector2& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector2 R; + XMStoreFloat2( &R, X ); + return R; +} + +//------------------------------------------------------------------------------ +// Vector operations +//------------------------------------------------------------------------------ + +inline bool Vector2::InBounds( const Vector2& Bounds ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &Bounds ); + return XMVector2InBounds( v1, v2 ); +} + +inline float Vector2::Length() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVector2Length( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector2::LengthSquared() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVector2LengthSq( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector2::Dot( const Vector2& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR X = XMVector2Dot( v1, v2 ); + return XMVectorGetX( X ); +} + +inline void Vector2::Cross( const Vector2& V, Vector2& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR R = XMVector2Cross( v1, v2 ); + XMStoreFloat2( &result, R ); +} + +inline Vector2 Vector2::Cross( const Vector2& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &V ); + XMVECTOR R = XMVector2Cross( v1, v2 ); + + Vector2 result; + XMStoreFloat2( &result, R ); + return result; +} + +inline void Vector2::Normalize() +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVector2Normalize( v1 ); + XMStoreFloat2( this, X ); +} + +inline void Vector2::Normalize( Vector2& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR X = XMVector2Normalize( v1 ); + XMStoreFloat2( &result, X ); +} + +inline void Vector2::Clamp( const Vector2& vmin, const Vector2& vmax ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &vmin ); + XMVECTOR v3 = XMLoadFloat2( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat2( this, X ); +} + +inline void Vector2::Clamp( const Vector2& vmin, const Vector2& vmax, Vector2& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( this ); + XMVECTOR v2 = XMLoadFloat2( &vmin ); + XMVECTOR v3 = XMLoadFloat2( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat2( &result, X ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline float Vector2::Distance( const Vector2& v1, const Vector2& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector2Length( V ); + return XMVectorGetX( X ); +} + +inline float Vector2::DistanceSquared( const Vector2& v1, const Vector2& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector2LengthSq( V ); + return XMVectorGetX( X ); +} + +inline void Vector2::Min( const Vector2& v1, const Vector2& v2, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Min( const Vector2& v1, const Vector2& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Max( const Vector2& v1, const Vector2& v2, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Max( const Vector2& v1, const Vector2& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Lerp( const Vector2& v1, const Vector2& v2, float t, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Lerp( const Vector2& v1, const Vector2& v2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::SmoothStep( const Vector2& v1, const Vector2& v2, float t, Vector2& result ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::SmoothStep( const Vector2& v1, const Vector2& v2, float t ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Barycentric( const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR x3 = XMLoadFloat2( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Barycentric( const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR x3 = XMLoadFloat2( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::CatmullRom( const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR x3 = XMLoadFloat2( &v3 ); + XMVECTOR x4 = XMLoadFloat2( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::CatmullRom( const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &v2 ); + XMVECTOR x3 = XMLoadFloat2( &v3 ); + XMVECTOR x4 = XMLoadFloat2( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Hermite( const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &t1 ); + XMVECTOR x3 = XMLoadFloat2( &v2 ); + XMVECTOR x4 = XMLoadFloat2( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Hermite( const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat2( &v1 ); + XMVECTOR x2 = XMLoadFloat2( &t1 ); + XMVECTOR x3 = XMLoadFloat2( &v2 ); + XMVECTOR x4 = XMLoadFloat2( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Reflect( const Vector2& ivec, const Vector2& nvec, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat2( &ivec ); + XMVECTOR n = XMLoadFloat2( &nvec ); + XMVECTOR X = XMVector2Reflect( i, n ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Reflect( const Vector2& ivec, const Vector2& nvec ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat2( &ivec ); + XMVECTOR n = XMLoadFloat2( &nvec ); + XMVECTOR X = XMVector2Reflect( i, n ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Refract( const Vector2& ivec, const Vector2& nvec, float refractionIndex, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat2( &ivec ); + XMVECTOR n = XMLoadFloat2( &nvec ); + XMVECTOR X = XMVector2Refract( i, n, refractionIndex ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Refract( const Vector2& ivec, const Vector2& nvec, float refractionIndex ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat2( &ivec ); + XMVECTOR n = XMLoadFloat2( &nvec ); + XMVECTOR X = XMVector2Refract( i, n, refractionIndex ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Transform( const Vector2& v, const Quaternion& quat, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Transform( const Vector2& v, const Quaternion& quat ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +inline void Vector2::Transform( const Vector2& v, const Matrix& m, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector2TransformCoord( v1, M ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::Transform( const Vector2& v, const Matrix& m ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector2TransformCoord( v1, M ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +_Use_decl_annotations_ +inline void Vector2::Transform( const Vector2* varray, size_t count, const Matrix& m, Vector2* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector2TransformCoordStream( resultArray, sizeof(XMFLOAT2), varray, sizeof(XMFLOAT2), count, M ); +} + +inline void Vector2::Transform( const Vector2& v, const Matrix& m, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector2Transform( v1, M ); + XMStoreFloat4( &result, X ); +} + +_Use_decl_annotations_ +inline void Vector2::Transform( const Vector2* varray, size_t count, const Matrix& m, Vector4* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector2TransformStream( resultArray, sizeof(XMFLOAT4), varray, sizeof(XMFLOAT2), count, M ); +} + +inline void Vector2::TransformNormal( const Vector2& v, const Matrix& m, Vector2& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector2TransformNormal( v1, M ); + XMStoreFloat2( &result, X ); +} + +inline Vector2 Vector2::TransformNormal( const Vector2& v, const Matrix& m ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector2TransformNormal( v1, M ); + + Vector2 result; + XMStoreFloat2( &result, X ); + return result; +} + +_Use_decl_annotations_ +inline void Vector2::TransformNormal( const Vector2* varray, size_t count, const Matrix& m, Vector2* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector2TransformNormalStream( resultArray, sizeof(XMFLOAT2), varray, sizeof(XMFLOAT2), count, M ); +} + + +/**************************************************************************** + * + * Vector3 + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Vector3::operator == ( const Vector3& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + return XMVector3Equal( v1, v2 ); +} + +inline bool Vector3::operator != ( const Vector3& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + return XMVector3NotEqual( v1, v2 ); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Vector3& Vector3::operator+= (const Vector3& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR X = XMVectorAdd(v1,v2); + XMStoreFloat3( this, X ); + return *this; +} + +inline Vector3& Vector3::operator-= (const Vector3& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR X = XMVectorSubtract(v1,v2); + XMStoreFloat3( this, X ); + return *this; +} + +inline Vector3& Vector3::operator*= (const Vector3& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR X = XMVectorMultiply(v1,v2); + XMStoreFloat3( this, X ); + return *this; +} + +inline Vector3& Vector3::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVectorScale(v1,S); + XMStoreFloat3( this, X ); + return *this; +} + +inline Vector3& Vector3::operator/= (float S) +{ + using namespace DirectX; + assert( S != 0.0f ); + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVectorScale(v1, 1.f/S); + XMStoreFloat3( this, X ); + return *this; +} + +//------------------------------------------------------------------------------ +// Urnary operators +//------------------------------------------------------------------------------ + +inline Vector3 Vector3::operator- () const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVectorNegate( v1 ); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Vector3 operator+ (const Vector3& V1, const Vector3& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V1 ); + XMVECTOR v2 = XMLoadFloat3( &V2 ); + XMVECTOR X = XMVectorAdd(v1,v2); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +inline Vector3 operator- (const Vector3& V1, const Vector3& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V1 ); + XMVECTOR v2 = XMLoadFloat3( &V2 ); + XMVECTOR X = XMVectorSubtract(v1,v2); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +inline Vector3 operator* (const Vector3& V1, const Vector3& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V1 ); + XMVECTOR v2 = XMLoadFloat3( &V2 ); + XMVECTOR X = XMVectorMultiply(v1,v2); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +inline Vector3 operator* (const Vector3& V, float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +inline Vector3 operator/ (const Vector3& V1, const Vector3& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V1 ); + XMVECTOR v2 = XMLoadFloat3( &V2 ); + XMVECTOR X = XMVectorDivide(v1,v2); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +inline Vector3 operator* (float S, const Vector3& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector3 R; + XMStoreFloat3( &R, X ); + return R; +} + +//------------------------------------------------------------------------------ +// Vector operations +//------------------------------------------------------------------------------ + +inline bool Vector3::InBounds( const Vector3& Bounds ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &Bounds ); + return XMVector3InBounds( v1, v2 ); +} + +inline float Vector3::Length() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVector3Length( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector3::LengthSquared() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVector3LengthSq( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector3::Dot( const Vector3& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR X = XMVector3Dot( v1, v2 ); + return XMVectorGetX( X ); +} + +inline void Vector3::Cross( const Vector3& V, Vector3& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR R = XMVector3Cross( v1, v2 ); + XMStoreFloat3( &result, R ); +} + +inline Vector3 Vector3::Cross( const Vector3& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &V ); + XMVECTOR R = XMVector3Cross( v1, v2 ); + + Vector3 result; + XMStoreFloat3( &result, R ); + return result; +} + +inline void Vector3::Normalize() +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVector3Normalize( v1 ); + XMStoreFloat3( this, X ); +} + +inline void Vector3::Normalize( Vector3& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR X = XMVector3Normalize( v1 ); + XMStoreFloat3( &result, X ); +} + +inline void Vector3::Clamp( const Vector3& vmin, const Vector3& vmax ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &vmin ); + XMVECTOR v3 = XMLoadFloat3( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat3( this, X ); +} + +inline void Vector3::Clamp( const Vector3& vmin, const Vector3& vmax, Vector3& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( this ); + XMVECTOR v2 = XMLoadFloat3( &vmin ); + XMVECTOR v3 = XMLoadFloat3( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat3( &result, X ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline float Vector3::Distance( const Vector3& v1, const Vector3& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector3Length( V ); + return XMVectorGetX( X ); +} + +inline float Vector3::DistanceSquared( const Vector3& v1, const Vector3& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector3LengthSq( V ); + return XMVectorGetX( X ); +} + +inline void Vector3::Min( const Vector3& v1, const Vector3& v2, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Min( const Vector3& v1, const Vector3& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Max( const Vector3& v1, const Vector3& v2, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Max( const Vector3& v1, const Vector3& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Lerp( const Vector3& v1, const Vector3& v2, float t, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Lerp( const Vector3& v1, const Vector3& v2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::SmoothStep( const Vector3& v1, const Vector3& v2, float t, Vector3& result ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::SmoothStep( const Vector3& v1, const Vector3& v2, float t ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Barycentric( const Vector3& v1, const Vector3& v2, const Vector3& v3, float f, float g, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR x3 = XMLoadFloat3( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Barycentric( const Vector3& v1, const Vector3& v2, const Vector3& v3, float f, float g ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR x3 = XMLoadFloat3( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::CatmullRom( const Vector3& v1, const Vector3& v2, const Vector3& v3, const Vector3& v4, float t, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR x3 = XMLoadFloat3( &v3 ); + XMVECTOR x4 = XMLoadFloat3( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::CatmullRom( const Vector3& v1, const Vector3& v2, const Vector3& v3, const Vector3& v4, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &v2 ); + XMVECTOR x3 = XMLoadFloat3( &v3 ); + XMVECTOR x4 = XMLoadFloat3( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Hermite( const Vector3& v1, const Vector3& t1, const Vector3& v2, const Vector3& t2, float t, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &t1 ); + XMVECTOR x3 = XMLoadFloat3( &v2 ); + XMVECTOR x4 = XMLoadFloat3( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Hermite( const Vector3& v1, const Vector3& t1, const Vector3& v2, const Vector3& t2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat3( &v1 ); + XMVECTOR x2 = XMLoadFloat3( &t1 ); + XMVECTOR x3 = XMLoadFloat3( &v2 ); + XMVECTOR x4 = XMLoadFloat3( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Reflect( const Vector3& ivec, const Vector3& nvec, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat3( &ivec ); + XMVECTOR n = XMLoadFloat3( &nvec ); + XMVECTOR X = XMVector3Reflect( i, n ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Reflect( const Vector3& ivec, const Vector3& nvec ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat3( &ivec ); + XMVECTOR n = XMLoadFloat3( &nvec ); + XMVECTOR X = XMVector3Reflect( i, n ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Refract( const Vector3& ivec, const Vector3& nvec, float refractionIndex, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat3( &ivec ); + XMVECTOR n = XMLoadFloat3( &nvec ); + XMVECTOR X = XMVector3Refract( i, n, refractionIndex ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Refract( const Vector3& ivec, const Vector3& nvec, float refractionIndex ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat3( &ivec ); + XMVECTOR n = XMLoadFloat3( &nvec ); + XMVECTOR X = XMVector3Refract( i, n, refractionIndex ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Transform( const Vector3& v, const Quaternion& quat, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Transform( const Vector3& v, const Quaternion& quat ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +inline void Vector3::Transform( const Vector3& v, const Matrix& m, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector3TransformCoord( v1, M ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::Transform( const Vector3& v, const Matrix& m ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector3TransformCoord( v1, M ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +_Use_decl_annotations_ +inline void Vector3::Transform( const Vector3* varray, size_t count, const Matrix& m, Vector3* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector3TransformCoordStream( resultArray, sizeof(XMFLOAT3), varray, sizeof(XMFLOAT3), count, M ); +} + +inline void Vector3::Transform( const Vector3& v, const Matrix& m, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector3Transform( v1, M ); + XMStoreFloat4( &result, X ); +} + +_Use_decl_annotations_ +inline void Vector3::Transform( const Vector3* varray, size_t count, const Matrix& m, Vector4* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector3TransformStream( resultArray, sizeof(XMFLOAT4), varray, sizeof(XMFLOAT3), count, M ); +} + +inline void Vector3::TransformNormal( const Vector3& v, const Matrix& m, Vector3& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector3TransformNormal( v1, M ); + XMStoreFloat3( &result, X ); +} + +inline Vector3 Vector3::TransformNormal( const Vector3& v, const Matrix& m ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector3TransformNormal( v1, M ); + + Vector3 result; + XMStoreFloat3( &result, X ); + return result; +} + +_Use_decl_annotations_ +inline void Vector3::TransformNormal( const Vector3* varray, size_t count, const Matrix& m, Vector3* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector3TransformNormalStream( resultArray, sizeof(XMFLOAT3), varray, sizeof(XMFLOAT3), count, M ); +} + + +/**************************************************************************** + * + * Vector4 + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Vector4::operator == ( const Vector4& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + return XMVector4Equal( v1, v2 ); +} + +inline bool Vector4::operator != ( const Vector4& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + return XMVector4NotEqual( v1, v2 ); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Vector4& Vector4::operator+= (const Vector4& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + XMVECTOR X = XMVectorAdd(v1,v2); + XMStoreFloat4( this, X ); + return *this; +} + +inline Vector4& Vector4::operator-= (const Vector4& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + XMVECTOR X = XMVectorSubtract(v1,v2); + XMStoreFloat4( this, X ); + return *this; +} + +inline Vector4& Vector4::operator*= (const Vector4& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + XMVECTOR X = XMVectorMultiply(v1,v2); + XMStoreFloat4( this, X ); + return *this; +} + +inline Vector4& Vector4::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVectorScale(v1,S); + XMStoreFloat4( this, X ); + return *this; +} + +inline Vector4& Vector4::operator/= (float S) +{ + using namespace DirectX; + assert( S != 0.0f ); + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVectorScale(v1, 1.f/S); + XMStoreFloat4( this, X ); + return *this; +} + +//------------------------------------------------------------------------------ +// Urnary operators +//------------------------------------------------------------------------------ + +inline Vector4 Vector4::operator- () const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVectorNegate( v1 ); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Vector4 operator+ (const Vector4& V1, const Vector4& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V1 ); + XMVECTOR v2 = XMLoadFloat4( &V2 ); + XMVECTOR X = XMVectorAdd(v1,v2); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +inline Vector4 operator- (const Vector4& V1, const Vector4& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V1 ); + XMVECTOR v2 = XMLoadFloat4( &V2 ); + XMVECTOR X = XMVectorSubtract(v1,v2); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +inline Vector4 operator* (const Vector4& V1, const Vector4& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V1 ); + XMVECTOR v2 = XMLoadFloat4( &V2 ); + XMVECTOR X = XMVectorMultiply(v1,v2); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +inline Vector4 operator* (const Vector4& V, float S) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +inline Vector4 operator/ (const Vector4& V1, const Vector4& V2) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V1 ); + XMVECTOR v2 = XMLoadFloat4( &V2 ); + XMVECTOR X = XMVectorDivide(v1,v2); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +inline Vector4 operator* (float S, const Vector4& V) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &V ); + XMVECTOR X = XMVectorScale(v1,S); + Vector4 R; + XMStoreFloat4( &R, X ); + return R; +} + +//------------------------------------------------------------------------------ +// Vector operations +//------------------------------------------------------------------------------ + +inline bool Vector4::InBounds( const Vector4& Bounds ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &Bounds ); + return XMVector4InBounds( v1, v2 ); +} + +inline float Vector4::Length() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVector4Length( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector4::LengthSquared() const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVector4LengthSq( v1 ); + return XMVectorGetX( X ); +} + +inline float Vector4::Dot( const Vector4& V ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &V ); + XMVECTOR X = XMVector4Dot( v1, v2 ); + return XMVectorGetX( X ); +} + +inline void Vector4::Cross( const Vector4& v1, const Vector4& v2, Vector4& result ) const +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( this ); + XMVECTOR x2 = XMLoadFloat4( &v1 ); + XMVECTOR x3 = XMLoadFloat4( &v2 ); + XMVECTOR R = XMVector4Cross( x1, x2, x3 ); + XMStoreFloat4( &result, R ); +} + +inline Vector4 Vector4::Cross( const Vector4& v1, const Vector4& v2 ) const +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( this ); + XMVECTOR x2 = XMLoadFloat4( &v1 ); + XMVECTOR x3 = XMLoadFloat4( &v2 ); + XMVECTOR R = XMVector4Cross( x1, x2, x3 ); + + Vector4 result; + XMStoreFloat4( &result, R ); + return result; +} + +inline void Vector4::Normalize() +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVector4Normalize( v1 ); + XMStoreFloat4( this, X ); +} + +inline void Vector4::Normalize( Vector4& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR X = XMVector4Normalize( v1 ); + XMStoreFloat4( &result, X ); +} + +inline void Vector4::Clamp( const Vector4& vmin, const Vector4& vmax ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &vmin ); + XMVECTOR v3 = XMLoadFloat4( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat4( this, X ); +} + +inline void Vector4::Clamp( const Vector4& vmin, const Vector4& vmax, Vector4& result ) const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( this ); + XMVECTOR v2 = XMLoadFloat4( &vmin ); + XMVECTOR v3 = XMLoadFloat4( &vmax ); + XMVECTOR X = XMVectorClamp( v1, v2, v3 ); + XMStoreFloat4( &result, X ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline float Vector4::Distance( const Vector4& v1, const Vector4& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector4Length( V ); + return XMVectorGetX( X ); +} + +inline float Vector4::DistanceSquared( const Vector4& v1, const Vector4& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR V = XMVectorSubtract( x2, x1 ); + XMVECTOR X = XMVector4LengthSq( V ); + return XMVectorGetX( X ); +} + +inline void Vector4::Min( const Vector4& v1, const Vector4& v2, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Min( const Vector4& v1, const Vector4& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorMin( x1, x2 ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Max( const Vector4& v1, const Vector4& v2, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Max( const Vector4& v1, const Vector4& v2 ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorMax( x1, x2 ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Lerp( const Vector4& v1, const Vector4& v2, float t, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Lerp( const Vector4& v1, const Vector4& v2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::SmoothStep( const Vector4& v1, const Vector4& v2, float t, Vector4& result ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::SmoothStep( const Vector4& v1, const Vector4& v2, float t ) +{ + using namespace DirectX; + t = (t > 1.0f) ? 1.0f : ((t < 0.0f) ? 0.0f : t); // Clamp value to 0 to 1 + t = t*t*(3.f - 2.f*t); + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR X = XMVectorLerp( x1, x2, t ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Barycentric( const Vector4& v1, const Vector4& v2, const Vector4& v3, float f, float g, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR x3 = XMLoadFloat4( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Barycentric( const Vector4& v1, const Vector4& v2, const Vector4& v3, float f, float g ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR x3 = XMLoadFloat4( &v3 ); + XMVECTOR X = XMVectorBaryCentric( x1, x2, x3, f, g ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::CatmullRom( const Vector4& v1, const Vector4& v2, const Vector4& v3, const Vector4& v4, float t, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR x3 = XMLoadFloat4( &v3 ); + XMVECTOR x4 = XMLoadFloat4( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::CatmullRom( const Vector4& v1, const Vector4& v2, const Vector4& v3, const Vector4& v4, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &v2 ); + XMVECTOR x3 = XMLoadFloat4( &v3 ); + XMVECTOR x4 = XMLoadFloat4( &v4 ); + XMVECTOR X = XMVectorCatmullRom( x1, x2, x3, x4, t ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Hermite( const Vector4& v1, const Vector4& t1, const Vector4& v2, const Vector4& t2, float t, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &t1 ); + XMVECTOR x3 = XMLoadFloat4( &v2 ); + XMVECTOR x4 = XMLoadFloat4( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Hermite( const Vector4& v1, const Vector4& t1, const Vector4& v2, const Vector4& t2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( &v1 ); + XMVECTOR x2 = XMLoadFloat4( &t1 ); + XMVECTOR x3 = XMLoadFloat4( &v2 ); + XMVECTOR x4 = XMLoadFloat4( &t2 ); + XMVECTOR X = XMVectorHermite( x1, x2, x3, x4, t ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Reflect( const Vector4& ivec, const Vector4& nvec, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat4( &ivec ); + XMVECTOR n = XMLoadFloat4( &nvec ); + XMVECTOR X = XMVector4Reflect( i, n ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Reflect( const Vector4& ivec, const Vector4& nvec ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat4( &ivec ); + XMVECTOR n = XMLoadFloat4( &nvec ); + XMVECTOR X = XMVector4Reflect( i, n ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Refract( const Vector4& ivec, const Vector4& nvec, float refractionIndex, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat4( &ivec ); + XMVECTOR n = XMLoadFloat4( &nvec ); + XMVECTOR X = XMVector4Refract( i, n, refractionIndex ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Refract( const Vector4& ivec, const Vector4& nvec, float refractionIndex ) +{ + using namespace DirectX; + XMVECTOR i = XMLoadFloat4( &ivec ); + XMVECTOR n = XMLoadFloat4( &nvec ); + XMVECTOR X = XMVector4Refract( i, n, refractionIndex ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Transform( const Vector2& v, const Quaternion& quat, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( g_XMIdentityR3, X, g_XMSelect1110 ); // result.w = 1.f + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Transform( const Vector2& v, const Quaternion& quat ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat2( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( g_XMIdentityR3, X, g_XMSelect1110 ); // result.w = 1.f + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Transform( const Vector3& v, const Quaternion& quat, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( g_XMIdentityR3, X, g_XMSelect1110 ); // result.w = 1.f + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Transform( const Vector3& v, const Quaternion& quat ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat3( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( g_XMIdentityR3, X, g_XMSelect1110 ); // result.w = 1.f + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Transform( const Vector4& v, const Quaternion& quat, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( v1, X, g_XMSelect1110 ); // result.w = v.w + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Transform( const Vector4& v, const Quaternion& quat ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &v ); + XMVECTOR q = XMLoadFloat4( &quat ); + XMVECTOR X = XMVector3Rotate( v1, q ); + X = XMVectorSelect( v1, X, g_XMSelect1110 ); // result.w = v.w + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +inline void Vector4::Transform( const Vector4& v, const Matrix& m, Vector4& result ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector4Transform( v1, M ); + XMStoreFloat4( &result, X ); +} + +inline Vector4 Vector4::Transform( const Vector4& v, const Matrix& m ) +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( &v ); + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVECTOR X = XMVector4Transform( v1, M ); + + Vector4 result; + XMStoreFloat4( &result, X ); + return result; +} + +_Use_decl_annotations_ +inline void Vector4::Transform( const Vector4* varray, size_t count, const Matrix& m, Vector4* resultArray ) +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( &m ); + XMVector4TransformStream( resultArray, sizeof(XMFLOAT4), varray, sizeof(XMFLOAT4), count, M ); +} + + +/**************************************************************************** + * + * Matrix + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Matrix::operator == ( const Matrix& M ) const +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + return ( XMVector4Equal( x1, y1 ) + && XMVector4Equal( x2, y2 ) + && XMVector4Equal( x3, y3 ) + && XMVector4Equal( x4, y4 ) ) != 0; +} + +inline bool Matrix::operator != ( const Matrix& M ) const +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + return ( XMVector4NotEqual( x1, y1 ) + || XMVector4NotEqual( x2, y2 ) + || XMVector4NotEqual( x3, y3 ) + || XMVector4NotEqual( x4, y4 ) ) != 0; +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Matrix::Matrix(const XMFLOAT3X3& M) +{ + _11 = M._11; _12 = M._12; _13 = M._13; _14 = 0.f; + _21 = M._21; _22 = M._22; _23 = M._23; _24 = 0.f; + _31 = M._31; _32 = M._32; _33 = M._33; _34 = 0.f; + _41 = 0.f; _42 = 0.f; _43 = 0.f; _44 = 1.f; +} + +inline Matrix::Matrix(const XMFLOAT4X3& M) +{ + _11 = M._11; _12 = M._12; _13 = M._13; _14 = 0.f; + _21 = M._21; _22 = M._22; _23 = M._23; _24 = 0.f; + _31 = M._31; _32 = M._32; _33 = M._33; _34 = 0.f; + _41 = M._41; _42 = M._42; _43 = M._43; _44 = 1.f; +} + +inline Matrix& Matrix::operator= (const XMFLOAT3X3& M) +{ + _11 = M._11; _12 = M._12; _13 = M._13; _14 = 0.f; + _21 = M._21; _22 = M._22; _23 = M._23; _24 = 0.f; + _31 = M._31; _32 = M._32; _33 = M._33; _34 = 0.f; + _41 = 0.f; _42 = 0.f; _43 = 0.f; _44 = 1.f; + return *this; +} + +inline Matrix& Matrix::operator= (const XMFLOAT4X3& M) +{ + _11 = M._11; _12 = M._12; _13 = M._13; _14 = 0.f; + _21 = M._21; _22 = M._22; _23 = M._23; _24 = 0.f; + _31 = M._31; _32 = M._32; _33 = M._33; _34 = 0.f; + _41 = M._41; _42 = M._42; _43 = M._43; _44 = 1.f; + return *this; +} + +inline Matrix& Matrix::operator+= (const Matrix& M) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + x1 = XMVectorAdd( x1, y1 ); + x2 = XMVectorAdd( x2, y2 ); + x3 = XMVectorAdd( x3, y3 ); + x4 = XMVectorAdd( x4, y4 ); + + XMStoreFloat4( reinterpret_cast(&_11), x1 ); + XMStoreFloat4( reinterpret_cast(&_21), x2 ); + XMStoreFloat4( reinterpret_cast(&_31), x3 ); + XMStoreFloat4( reinterpret_cast(&_41), x4 ); + return *this; +} + +inline Matrix& Matrix::operator-= (const Matrix& M) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + x1 = XMVectorSubtract( x1, y1 ); + x2 = XMVectorSubtract( x2, y2 ); + x3 = XMVectorSubtract( x3, y3 ); + x4 = XMVectorSubtract( x4, y4 ); + + XMStoreFloat4( reinterpret_cast(&_11), x1 ); + XMStoreFloat4( reinterpret_cast(&_21), x2 ); + XMStoreFloat4( reinterpret_cast(&_31), x3 ); + XMStoreFloat4( reinterpret_cast(&_41), x4 ); + return *this; +} + +inline Matrix& Matrix::operator*= (const Matrix& M) +{ + using namespace DirectX; + XMMATRIX M1 = XMLoadFloat4x4( this ); + XMMATRIX M2 = XMLoadFloat4x4( &M ); + XMMATRIX X = XMMatrixMultiply( M1, M2 ); + XMStoreFloat4x4( this, X ); + return *this; +} + +inline Matrix& Matrix::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + x1 = XMVectorScale( x1, S ); + x2 = XMVectorScale( x2, S ); + x3 = XMVectorScale( x3, S ); + x4 = XMVectorScale( x4, S ); + + XMStoreFloat4( reinterpret_cast(&_11), x1 ); + XMStoreFloat4( reinterpret_cast(&_21), x2 ); + XMStoreFloat4( reinterpret_cast(&_31), x3 ); + XMStoreFloat4( reinterpret_cast(&_41), x4 ); + return *this; +} + +inline Matrix& Matrix::operator/= (float S) +{ + using namespace DirectX; + assert( S != 0.f ); + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + float rs = 1.f / S; + + x1 = XMVectorScale( x1, rs ); + x2 = XMVectorScale( x2, rs ); + x3 = XMVectorScale( x3, rs ); + x4 = XMVectorScale( x4, rs ); + + XMStoreFloat4( reinterpret_cast(&_11), x1 ); + XMStoreFloat4( reinterpret_cast(&_21), x2 ); + XMStoreFloat4( reinterpret_cast(&_31), x3 ); + XMStoreFloat4( reinterpret_cast(&_41), x4 ); + return *this; +} + +inline Matrix& Matrix::operator/= (const Matrix& M) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + x1 = XMVectorDivide( x1, y1 ); + x2 = XMVectorDivide( x2, y2 ); + x3 = XMVectorDivide( x3, y3 ); + x4 = XMVectorDivide( x4, y4 ); + + XMStoreFloat4( reinterpret_cast(&_11), x1 ); + XMStoreFloat4( reinterpret_cast(&_21), x2 ); + XMStoreFloat4( reinterpret_cast(&_31), x3 ); + XMStoreFloat4( reinterpret_cast(&_41), x4 ); + return *this; +} + +//------------------------------------------------------------------------------ +// Urnary operators +//------------------------------------------------------------------------------ + +inline Matrix Matrix::operator- () const +{ + using namespace DirectX; + XMVECTOR v1 = XMLoadFloat4( reinterpret_cast(&_11) ); + XMVECTOR v2 = XMLoadFloat4( reinterpret_cast(&_21) ); + XMVECTOR v3 = XMLoadFloat4( reinterpret_cast(&_31) ); + XMVECTOR v4 = XMLoadFloat4( reinterpret_cast(&_41) ); + + v1 = XMVectorNegate( v1 ); + v2 = XMVectorNegate( v2 ); + v3 = XMVectorNegate( v3 ); + v4 = XMVectorNegate( v4 ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), v1 ); + XMStoreFloat4( reinterpret_cast(&R._21), v2 ); + XMStoreFloat4( reinterpret_cast(&R._31), v3 ); + XMStoreFloat4( reinterpret_cast(&R._41), v4 ); + return R; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Matrix operator+ (const Matrix& M1, const Matrix& M2) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M1._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M1._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M1._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M1._41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M2._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M2._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M2._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M2._41) ); + + x1 = XMVectorAdd( x1, y1 ); + x2 = XMVectorAdd( x2, y2 ); + x3 = XMVectorAdd( x3, y3 ); + x4 = XMVectorAdd( x4, y4 ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +inline Matrix operator- (const Matrix& M1, const Matrix& M2) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M1._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M1._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M1._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M1._41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M2._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M2._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M2._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M2._41) ); + + x1 = XMVectorSubtract( x1, y1 ); + x2 = XMVectorSubtract( x2, y2 ); + x3 = XMVectorSubtract( x3, y3 ); + x4 = XMVectorSubtract( x4, y4 ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +inline Matrix operator* (const Matrix& M1, const Matrix& M2) +{ + using namespace DirectX; + XMMATRIX m1 = XMLoadFloat4x4( &M1 ); + XMMATRIX m2 = XMLoadFloat4x4( &M2 ); + XMMATRIX X = XMMatrixMultiply( m1, m2 ); + + Matrix R; + XMStoreFloat4x4( &R, X ); + return R; +} + +inline Matrix operator* (const Matrix& M, float S) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + x1 = XMVectorScale( x1, S ); + x2 = XMVectorScale( x2, S ); + x3 = XMVectorScale( x3, S ); + x4 = XMVectorScale( x4, S ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +inline Matrix operator/ (const Matrix& M, float S) +{ + using namespace DirectX; + assert( S != 0.f ); + + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + float rs = 1.f / S; + + x1 = XMVectorScale( x1, rs ); + x2 = XMVectorScale( x2, rs ); + x3 = XMVectorScale( x3, rs ); + x4 = XMVectorScale( x4, rs ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +inline Matrix operator/ (const Matrix& M1, const Matrix& M2) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M1._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M1._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M1._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M1._41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M2._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M2._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M2._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M2._41) ); + + x1 = XMVectorDivide( x1, y1 ); + x2 = XMVectorDivide( x2, y2 ); + x3 = XMVectorDivide( x3, y3 ); + x4 = XMVectorDivide( x4, y4 ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +inline Matrix operator* (float S, const Matrix& M) +{ + using namespace DirectX; + + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M._41) ); + + x1 = XMVectorScale( x1, S ); + x2 = XMVectorScale( x2, S ); + x3 = XMVectorScale( x3, S ); + x4 = XMVectorScale( x4, S ); + + Matrix R; + XMStoreFloat4( reinterpret_cast(&R._11), x1 ); + XMStoreFloat4( reinterpret_cast(&R._21), x2 ); + XMStoreFloat4( reinterpret_cast(&R._31), x3 ); + XMStoreFloat4( reinterpret_cast(&R._41), x4 ); + return R; +} + +//------------------------------------------------------------------------------ +// Matrix operations +//------------------------------------------------------------------------------ + +inline bool Matrix::Decompose( Vector3& scale, Quaternion& rotation, Vector3& translation ) +{ + using namespace DirectX; + + XMVECTOR s, r, t; + + if ( !XMMatrixDecompose( &s, &r, &t, *this ) ) + return false; + + XMStoreFloat3( &scale, s ); + XMStoreFloat4( &rotation, r ); + XMStoreFloat3( &translation, t ); + + return true; +} + +inline Matrix Matrix::Transpose() const +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( this ); + Matrix R; + XMStoreFloat4x4( &R, XMMatrixTranspose( M ) ); + return R; +} + +inline void Matrix::Transpose( Matrix& result ) const +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( this ); + XMStoreFloat4x4( &result, XMMatrixTranspose( M ) ); +} + +inline Matrix Matrix::Invert() const +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( this ); + Matrix R; + XMVECTOR det; + XMStoreFloat4x4( &R, XMMatrixInverse( &det, M ) ); + return R; +} + +inline void Matrix::Invert( Matrix& result ) const +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( this ); + XMVECTOR det; + XMStoreFloat4x4( &result, XMMatrixInverse( &det, M ) ); +} + +inline float Matrix::Determinant() const +{ + using namespace DirectX; + XMMATRIX M = XMLoadFloat4x4( this ); + return XMVectorGetX( XMMatrixDeterminant( M ) ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +_Use_decl_annotations_ +inline Matrix Matrix::CreateBillboard( const Vector3& object, const Vector3& cameraPosition, const Vector3& cameraUp, const Vector3* cameraForward ) +{ + using namespace DirectX; + XMVECTOR O = XMLoadFloat3( &object ); + XMVECTOR C = XMLoadFloat3( &cameraPosition ); + XMVECTOR Z = XMVectorSubtract( O, C ); + + XMVECTOR N = XMVector3LengthSq( Z ); + if ( XMVector3Less( N, g_XMEpsilon ) ) + { + if ( cameraForward ) + { + XMVECTOR F = XMLoadFloat3( cameraForward ); + Z = XMVectorNegate( F ); + } + else + Z = g_XMNegIdentityR2; + } + else + { + Z = XMVector3Normalize( Z ); + } + + XMVECTOR up = XMLoadFloat3( &cameraUp ); + XMVECTOR X = XMVector3Cross( up, Z ); + X = XMVector3Normalize( X ); + + XMVECTOR Y = XMVector3Cross( Z, X ); + + XMMATRIX M; + M.r[0] = X; + M.r[1] = Y; + M.r[2] = Z; + M.r[3] = XMVectorSetW( O, 1.f ); + + Matrix R; + XMStoreFloat4x4( &R, M ); + return R; +} + +_Use_decl_annotations_ +inline Matrix Matrix::CreateConstrainedBillboard( const Vector3& object, const Vector3& cameraPosition, const Vector3& rotateAxis, + const Vector3* cameraForward, const Vector3* objectForward ) +{ + using namespace DirectX; + + static const XMVECTORF32 s_minAngle = { 0.99825467075f, 0.99825467075f, 0.99825467075f, 0.99825467075f }; // 1.0 - XMConvertToRadians( 0.1f ); + + XMVECTOR O = XMLoadFloat3( &object ); + XMVECTOR C = XMLoadFloat3( &cameraPosition ); + XMVECTOR faceDir = XMVectorSubtract( O, C ); + + XMVECTOR N = XMVector3LengthSq( faceDir ); + if (XMVector3Less(N, g_XMEpsilon)) + { + if (cameraForward) + { + XMVECTOR F = XMLoadFloat3( cameraForward ); + faceDir = XMVectorNegate( F ); + } + else + faceDir = g_XMNegIdentityR2; + } + else + { + faceDir = XMVector3Normalize( faceDir ); + } + + XMVECTOR Y = XMLoadFloat3( &rotateAxis ); + XMVECTOR X, Z; + + XMVECTOR dot = XMVectorAbs( XMVector3Dot( Y, faceDir ) ); + if ( XMVector3Greater( dot, s_minAngle ) ) + { + if ( objectForward ) + { + Z = XMLoadFloat3( objectForward ); + dot = XMVectorAbs( XMVector3Dot( Y, Z ) ); + if ( XMVector3Greater( dot, s_minAngle ) ) + { + dot = XMVectorAbs( XMVector3Dot( Y, g_XMNegIdentityR2 ) ); + Z = ( XMVector3Greater( dot, s_minAngle ) ) ? g_XMIdentityR0 : g_XMNegIdentityR2; + } + } + else + { + dot = XMVectorAbs( XMVector3Dot( Y, g_XMNegIdentityR2 ) ); + Z = ( XMVector3Greater( dot, s_minAngle ) ) ? g_XMIdentityR0 : g_XMNegIdentityR2; + } + + X = XMVector3Cross( Y, Z ); + X = XMVector3Normalize( X ); + + Z = XMVector3Cross( X, Y ); + Z = XMVector3Normalize( Z ); + } + else + { + X = XMVector3Cross( Y, faceDir ); + X = XMVector3Normalize( X ); + + Z = XMVector3Cross( X, Y ); + Z = XMVector3Normalize( Z ); + } + + XMMATRIX M; + M.r[0] = X; + M.r[1] = Y; + M.r[2] = Z; + M.r[3] = XMVectorSetW( O, 1.f ); + + Matrix R; + XMStoreFloat4x4( &R, M ); + return R; +} + +inline Matrix Matrix::CreateTranslation( const Vector3& position ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixTranslation( position.x, position.y, position.z ) ); + return R; +} + +inline Matrix Matrix::CreateTranslation( float x, float y, float z ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixTranslation( x, y, z ) ); + return R; +} + +inline Matrix Matrix::CreateScale( const Vector3& scales ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixScaling( scales.x, scales.y, scales.z ) ); + return R; +} + +inline Matrix Matrix::CreateScale( float xs, float ys, float zs ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixScaling( xs, ys, zs ) ); + return R; +} + +inline Matrix Matrix::CreateScale( float scale ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixScaling( scale, scale, scale ) ); + return R; +} + +inline Matrix Matrix::CreateRotationX( float radians ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixRotationX( radians ) ); + return R; +} + +inline Matrix Matrix::CreateRotationY( float radians ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixRotationY( radians ) ); + return R; +} + +inline Matrix Matrix::CreateRotationZ( float radians ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixRotationZ( radians ) ); + return R; +} + +inline Matrix Matrix::CreateFromAxisAngle( const Vector3& axis, float angle ) +{ + using namespace DirectX; + Matrix R; + XMVECTOR a = XMLoadFloat3( &axis ); + XMStoreFloat4x4( &R, XMMatrixRotationAxis( a, angle ) ); + return R; +} + +inline Matrix Matrix::CreatePerspectiveFieldOfView( float fov, float aspectRatio, float nearPlane, float farPlane ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixPerspectiveFovRH( fov, aspectRatio, nearPlane, farPlane ) ); + return R; +} + +inline Matrix Matrix::CreatePerspective( float width, float height, float nearPlane, float farPlane ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixPerspectiveRH( width, height, nearPlane, farPlane ) ); + return R; +} + +inline Matrix Matrix::CreatePerspectiveOffCenter( float left, float right, float bottom, float top, float nearPlane, float farPlane ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixPerspectiveOffCenterRH( left, right, bottom, top, nearPlane, farPlane ) ); + return R; +} + +inline Matrix Matrix::CreateOrthographic( float width, float height, float zNearPlane, float zFarPlane ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixOrthographicRH( width, height, zNearPlane, zFarPlane ) ); + return R; +} + +inline Matrix Matrix::CreateOrthographicOffCenter( float left, float right, float bottom, float top, float zNearPlane, float zFarPlane ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixOrthographicOffCenterRH( left, right, bottom, top, zNearPlane, zFarPlane ) ); + return R; +} + +inline Matrix Matrix::CreateLookAt( const Vector3& eye, const Vector3& target, const Vector3& up ) +{ + using namespace DirectX; + Matrix R; + XMVECTOR eyev = XMLoadFloat3( &eye ); + XMVECTOR targetv = XMLoadFloat3( &target ); + XMVECTOR upv = XMLoadFloat3( &up ); + XMStoreFloat4x4( &R, XMMatrixLookAtRH( eyev, targetv, upv ) ); + return R; +} + +inline Matrix Matrix::CreateWorld( const Vector3& position, const Vector3& forward, const Vector3& up ) +{ + using namespace DirectX; + XMVECTOR zaxis = XMVector3Normalize( XMVectorNegate( XMLoadFloat3( &forward ) ) ); + XMVECTOR yaxis = XMLoadFloat3( &up ); + XMVECTOR xaxis = XMVector3Normalize( XMVector3Cross( yaxis, zaxis ) ); + yaxis = XMVector3Cross( zaxis, xaxis ); + + Matrix R; + XMStoreFloat3( reinterpret_cast( &R._11 ), xaxis ); + XMStoreFloat3( reinterpret_cast( &R._21 ), yaxis ); + XMStoreFloat3( reinterpret_cast( &R._31 ), zaxis ); + R._14 = R._24 = R._34 = 0.f; + R._41 = position.x; R._42 = position.y; R._43 = position.z; + R._44 = 1.f; + return R; +} + +inline Matrix Matrix::CreateFromQuaternion( const Quaternion& rotation ) +{ + using namespace DirectX; + Matrix R; + XMVECTOR quatv = XMLoadFloat4( &rotation ); + XMStoreFloat4x4( &R, XMMatrixRotationQuaternion( quatv ) ); + return R; +} + +inline Matrix Matrix::CreateFromYawPitchRoll( float yaw, float pitch, float roll ) +{ + using namespace DirectX; + Matrix R; + XMStoreFloat4x4( &R, XMMatrixRotationRollPitchYaw( pitch, yaw, roll ) ); + return R; +} + +inline Matrix Matrix::CreateShadow( const Vector3& lightDir, const Plane& plane ) +{ + using namespace DirectX; + Matrix R; + XMVECTOR light = XMLoadFloat3( &lightDir ); + XMVECTOR planev = XMLoadFloat4( &plane ); + XMStoreFloat4x4( &R, XMMatrixShadow( planev, light ) ); + return R; +} + +inline Matrix Matrix::CreateReflection( const Plane& plane ) +{ + using namespace DirectX; + Matrix R; + XMVECTOR planev = XMLoadFloat4( &plane ); + XMStoreFloat4x4( &R, XMMatrixReflect( planev ) ); + return R; +} + +inline void Matrix::Lerp( const Matrix& M1, const Matrix& M2, float t, Matrix& result ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M1._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M1._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M1._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M1._41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M2._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M2._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M2._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M2._41) ); + + x1 = XMVectorLerp( x1, y1, t ); + x2 = XMVectorLerp( x2, y2, t ); + x3 = XMVectorLerp( x3, y3, t ); + x4 = XMVectorLerp( x4, y4, t ); + + XMStoreFloat4( reinterpret_cast(&result._11), x1 ); + XMStoreFloat4( reinterpret_cast(&result._21), x2 ); + XMStoreFloat4( reinterpret_cast(&result._31), x3 ); + XMStoreFloat4( reinterpret_cast(&result._41), x4 ); +} + +inline Matrix Matrix::Lerp( const Matrix& M1, const Matrix& M2, float t ) +{ + using namespace DirectX; + XMVECTOR x1 = XMLoadFloat4( reinterpret_cast(&M1._11) ); + XMVECTOR x2 = XMLoadFloat4( reinterpret_cast(&M1._21) ); + XMVECTOR x3 = XMLoadFloat4( reinterpret_cast(&M1._31) ); + XMVECTOR x4 = XMLoadFloat4( reinterpret_cast(&M1._41) ); + + XMVECTOR y1 = XMLoadFloat4( reinterpret_cast(&M2._11) ); + XMVECTOR y2 = XMLoadFloat4( reinterpret_cast(&M2._21) ); + XMVECTOR y3 = XMLoadFloat4( reinterpret_cast(&M2._31) ); + XMVECTOR y4 = XMLoadFloat4( reinterpret_cast(&M2._41) ); + + x1 = XMVectorLerp( x1, y1, t ); + x2 = XMVectorLerp( x2, y2, t ); + x3 = XMVectorLerp( x3, y3, t ); + x4 = XMVectorLerp( x4, y4, t ); + + Matrix result; + XMStoreFloat4( reinterpret_cast(&result._11), x1 ); + XMStoreFloat4( reinterpret_cast(&result._21), x2 ); + XMStoreFloat4( reinterpret_cast(&result._31), x3 ); + XMStoreFloat4( reinterpret_cast(&result._41), x4 ); + return result; +} + +inline void Matrix::Transform( const Matrix& M, const Quaternion& rotation, Matrix& result ) +{ + using namespace DirectX; + XMVECTOR quatv = XMLoadFloat4( &rotation ); + + XMMATRIX M0 = XMLoadFloat4x4( &M ); + XMMATRIX M1 = XMMatrixRotationQuaternion( quatv ); + + XMStoreFloat4x4( &result, XMMatrixMultiply( M0, M1 ) ); +} + +inline Matrix Matrix::Transform( const Matrix& M, const Quaternion& rotation ) +{ + using namespace DirectX; + XMVECTOR quatv = XMLoadFloat4( &rotation ); + + XMMATRIX M0 = XMLoadFloat4x4( &M ); + XMMATRIX M1 = XMMatrixRotationQuaternion( quatv ); + + Matrix result; + XMStoreFloat4x4( &result, XMMatrixMultiply( M0, M1 ) ); + return result; +} + + +/**************************************************************************** + * + * Plane + * + ****************************************************************************/ + +inline Plane::Plane(const Vector3& point1, const Vector3& point2, const Vector3& point3 ) +{ + using namespace DirectX; + XMVECTOR P0 = XMLoadFloat3( &point1 ); + XMVECTOR P1 = XMLoadFloat3( &point2 ); + XMVECTOR P2 = XMLoadFloat3( &point3 ); + XMStoreFloat4( this, XMPlaneFromPoints( P0, P1, P2 ) ); +} + +inline Plane::Plane(const Vector3& point, const Vector3& normal) +{ + using namespace DirectX; + XMVECTOR P = XMLoadFloat3( &point ); + XMVECTOR N = XMLoadFloat3( &normal ); + XMStoreFloat4( this, XMPlaneFromPointNormal( P, N ) ); +} + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Plane::operator == ( const Plane& p ) const +{ + using namespace DirectX; + XMVECTOR p1 = XMLoadFloat4( this ); + XMVECTOR p2 = XMLoadFloat4( &p ); + return XMPlaneEqual( p1, p2 ); +} + +inline bool Plane::operator != ( const Plane& p ) const +{ + using namespace DirectX; + XMVECTOR p1 = XMLoadFloat4( this ); + XMVECTOR p2 = XMLoadFloat4( &p ); + return XMPlaneNotEqual( p1, p2 ); +} + +//------------------------------------------------------------------------------ +// Plane operations +//------------------------------------------------------------------------------ + +inline void Plane::Normalize() +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( this ); + XMStoreFloat4( this, XMPlaneNormalize( p ) ); +} + +inline void Plane::Normalize( Plane& result ) const +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMPlaneNormalize( p ) ); +} + +inline float Plane::Dot( const Vector4& v ) const +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( this ); + XMVECTOR v0 = XMLoadFloat4( &v ); + return XMVectorGetX( XMPlaneDot( p, v0 ) ); +} + +inline float Plane::DotCoordinate( const Vector3& position ) const +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( this ); + XMVECTOR v0 = XMLoadFloat3( &position ); + return XMVectorGetX( XMPlaneDotCoord( p, v0 ) ); +} + +inline float Plane::DotNormal( const Vector3& normal ) const +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( this ); + XMVECTOR n0 = XMLoadFloat3( &normal ); + return XMVectorGetX( XMPlaneDotNormal( p, n0 ) ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline void Plane::Transform( const Plane& plane, const Matrix& M, Plane& result ) +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( &plane ); + XMMATRIX m0 = XMLoadFloat4x4( &M ); + XMStoreFloat4( &result, XMPlaneTransform( p, m0 ) ); +} + +inline Plane Plane::Transform( const Plane& plane, const Matrix& M ) +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( &plane ); + XMMATRIX m0 = XMLoadFloat4x4( &M ); + + Plane result; + XMStoreFloat4( &result, XMPlaneTransform( p, m0 ) ); + return result; +} + +inline void Plane::Transform( const Plane& plane, const Quaternion& rotation, Plane& result ) +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( &plane ); + XMVECTOR q = XMLoadFloat4( &rotation ); + XMVECTOR X = XMVector3Rotate( p, q ); + X = XMVectorSelect( p, X, g_XMSelect1110 ); // result.d = plane.d + XMStoreFloat4( &result, X ); +} + +inline Plane Plane::Transform( const Plane& plane, const Quaternion& rotation ) +{ + using namespace DirectX; + XMVECTOR p = XMLoadFloat4( &plane ); + XMVECTOR q = XMLoadFloat4( &rotation ); + XMVECTOR X = XMVector3Rotate( p, q ); + X = XMVectorSelect( p, X, g_XMSelect1110 ); // result.d = plane.d + + Plane result; + XMStoreFloat4( &result, X ); + return result; +} + + +/**************************************************************************** + * + * Quaternion + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Quaternion::operator == ( const Quaternion& q ) const +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + return XMQuaternionEqual( q1, q2 ); +} + +inline bool Quaternion::operator != ( const Quaternion& q ) const +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + return XMQuaternionNotEqual( q1, q2 ); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Quaternion& Quaternion::operator+= (const Quaternion& q) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + XMStoreFloat4( this, XMVectorAdd( q1, q2 ) ); + return *this; +} + +inline Quaternion& Quaternion::operator-= (const Quaternion& q) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + XMStoreFloat4( this, XMVectorSubtract( q1, q2 ) ); + return *this; +} + +inline Quaternion& Quaternion::operator*= (const Quaternion& q) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + XMStoreFloat4( this, XMQuaternionMultiply( q1, q2 ) ); + return *this; +} + +inline Quaternion& Quaternion::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( this, XMVectorScale( q, S ) ); + return *this; +} + +inline Quaternion& Quaternion::operator/= (const Quaternion& q) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + q2 = XMQuaternionInverse( q2 ); + XMStoreFloat4( this, XMQuaternionMultiply( q1, q2 ) ); + return *this; +} + +//------------------------------------------------------------------------------ +// Urnary operators +//------------------------------------------------------------------------------ + +inline Quaternion Quaternion::operator- () const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + + Quaternion R; + XMStoreFloat4( &R, XMVectorNegate( q ) ); + return R; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Quaternion operator+ (const Quaternion& Q1, const Quaternion& Q2) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( &Q1 ); + XMVECTOR q2 = XMLoadFloat4( &Q2 ); + + Quaternion R; + XMStoreFloat4( &R, XMVectorAdd( q1, q2 ) ); + return R; +} + +inline Quaternion operator- (const Quaternion& Q1, const Quaternion& Q2) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( &Q1 ); + XMVECTOR q2 = XMLoadFloat4( &Q2 ); + + Quaternion R; + XMStoreFloat4( &R, XMVectorSubtract( q1, q2 ) ); + return R; +} + +inline Quaternion operator* (const Quaternion& Q1, const Quaternion& Q2) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( &Q1 ); + XMVECTOR q2 = XMLoadFloat4( &Q2 ); + + Quaternion R; + XMStoreFloat4( &R, XMQuaternionMultiply( q1, q2 ) ); + return R; +} + +inline Quaternion operator* (const Quaternion& Q, float S) +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( &Q ); + + Quaternion R; + XMStoreFloat4( &R, XMVectorScale( q, S ) ); + return R; +} + +inline Quaternion operator/ (const Quaternion& Q1, const Quaternion& Q2) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( &Q1 ); + XMVECTOR q2 = XMLoadFloat4( &Q2 ); + q2 = XMQuaternionInverse( q2 ); + + Quaternion R; + XMStoreFloat4( &R, XMQuaternionMultiply( q1, q2 ) ); + return R; +} + +inline Quaternion operator* (float S, const Quaternion& Q) +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( &Q ); + + Quaternion R; + XMStoreFloat4( &R, XMVectorScale( q1, S ) ); + return R; +} + +//------------------------------------------------------------------------------ +// Quaternion operations +//------------------------------------------------------------------------------ + +inline float Quaternion::Length() const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + return XMVectorGetX( XMQuaternionLength( q ) ); +} + +inline float Quaternion::LengthSquared() const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + return XMVectorGetX( XMQuaternionLengthSq( q ) ); +} + +inline void Quaternion::Normalize() +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( this, XMQuaternionNormalize( q ) ); +} + +inline void Quaternion::Normalize( Quaternion& result ) const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMQuaternionNormalize( q ) ); +} + +inline void Quaternion::Conjugate() +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( this, XMQuaternionConjugate( q ) ); +} + +inline void Quaternion::Conjugate( Quaternion& result ) const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMQuaternionConjugate( q ) ); +} + +inline void Quaternion::Inverse( Quaternion& result ) const +{ + using namespace DirectX; + XMVECTOR q = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMQuaternionInverse( q ) ); +} + +inline float Quaternion::Dot( const Quaternion& q ) const +{ + using namespace DirectX; + XMVECTOR q1 = XMLoadFloat4( this ); + XMVECTOR q2 = XMLoadFloat4( &q ); + return XMVectorGetX( XMQuaternionDot( q1, q2 ) ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline Quaternion Quaternion::CreateFromAxisAngle( const Vector3& axis, float angle ) +{ + using namespace DirectX; + XMVECTOR a = XMLoadFloat3( &axis ); + + Quaternion R; + XMStoreFloat4( &R, XMQuaternionRotationAxis( a, angle ) ); + return R; +} + +inline Quaternion Quaternion::CreateFromYawPitchRoll( float yaw, float pitch, float roll ) +{ + using namespace DirectX; + Quaternion R; + XMStoreFloat4( &R, XMQuaternionRotationRollPitchYaw( pitch, yaw, roll ) ); + return R; +} + +inline Quaternion Quaternion::CreateFromRotationMatrix( const Matrix& M ) +{ + using namespace DirectX; + XMMATRIX M0 = XMLoadFloat4x4( &M ); + + Quaternion R; + XMStoreFloat4( &R, XMQuaternionRotationMatrix( M0 ) ); + return R; +} + +inline void Quaternion::Lerp( const Quaternion& q1, const Quaternion& q2, float t, Quaternion& result ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + + XMVECTOR dot = XMVector4Dot( Q0, Q1 ); + + XMVECTOR R; + if ( XMVector4GreaterOrEqual( dot, XMVectorZero() ) ) + { + R = XMVectorLerp( Q0, Q1, t ); + } + else + { + XMVECTOR tv = XMVectorReplicate( t ); + XMVECTOR t1v = XMVectorReplicate( 1.f - t ); + XMVECTOR X0 = XMVectorMultiply( Q0, t1v ); + XMVECTOR X1 = XMVectorMultiply( Q1, tv ); + R = XMVectorSubtract( X0, X1 ); + } + + XMStoreFloat4( &result, XMQuaternionNormalize( R ) ); +} + +inline Quaternion Quaternion::Lerp( const Quaternion& q1, const Quaternion& q2, float t ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + + XMVECTOR dot = XMVector4Dot( Q0, Q1 ); + + XMVECTOR R; + if ( XMVector4GreaterOrEqual( dot, XMVectorZero() ) ) + { + R = XMVectorLerp( Q0, Q1, t ); + } + else + { + XMVECTOR tv = XMVectorReplicate( t ); + XMVECTOR t1v = XMVectorReplicate( 1.f - t ); + XMVECTOR X0 = XMVectorMultiply( Q0, t1v ); + XMVECTOR X1 = XMVectorMultiply( Q1, tv ); + R = XMVectorSubtract( X0, X1 ); + } + + Quaternion result; + XMStoreFloat4( &result, XMQuaternionNormalize( R ) ); + return result; +} + +inline void Quaternion::Slerp( const Quaternion& q1, const Quaternion& q2, float t, Quaternion& result ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + XMStoreFloat4( &result, XMQuaternionSlerp( Q0, Q1, t ) ); +} + +inline Quaternion Quaternion::Slerp( const Quaternion& q1, const Quaternion& q2, float t ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + + Quaternion result; + XMStoreFloat4( &result, XMQuaternionSlerp( Q0, Q1, t ) ); + return result; +} + +inline void Quaternion::Concatenate( const Quaternion& q1, const Quaternion& q2, Quaternion& result ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + XMStoreFloat4( &result, XMQuaternionMultiply( Q1, Q0 ) ); +} + +inline Quaternion Quaternion::Concatenate( const Quaternion& q1, const Quaternion& q2 ) +{ + using namespace DirectX; + XMVECTOR Q0 = XMLoadFloat4( &q1 ); + XMVECTOR Q1 = XMLoadFloat4( &q2 ); + + Quaternion result; + XMStoreFloat4( &result, XMQuaternionMultiply( Q1, Q0 ) ); + return result; +} + + +/**************************************************************************** + * + * Color + * + ****************************************************************************/ + +inline Color::Color( const DirectX::PackedVector::XMCOLOR& Packed ) +{ + using namespace DirectX; + XMStoreFloat4( this, PackedVector::XMLoadColor( &Packed ) ); +} + +inline Color::Color( const DirectX::PackedVector::XMUBYTEN4& Packed ) +{ + using namespace DirectX; + XMStoreFloat4( this, PackedVector::XMLoadUByteN4( &Packed ) ); +} + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ +inline bool Color::operator == ( const Color& c ) const +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + return XMColorEqual( c1, c2 ); +} + +inline bool Color::operator != ( const Color& c ) const +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + return XMColorNotEqual( c1, c2 ); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Color& Color::operator= (const DirectX::PackedVector::XMCOLOR& Packed) +{ + using namespace DirectX; + XMStoreFloat4( this, PackedVector::XMLoadColor( &Packed ) ); + return *this; +} + +inline Color& Color::operator= (const DirectX::PackedVector::XMUBYTEN4& Packed) +{ + using namespace DirectX; + XMStoreFloat4( this, PackedVector::XMLoadUByteN4( &Packed ) ); + return *this; +} + +inline Color& Color::operator+= (const Color& c) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + XMStoreFloat4( this, XMVectorAdd( c1, c2 ) ); + return *this; +} + +inline Color& Color::operator-= (const Color& c) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + XMStoreFloat4( this, XMVectorSubtract( c1, c2 ) ); + return *this; +} + +inline Color& Color::operator*= (const Color& c) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + XMStoreFloat4( this, XMVectorMultiply( c1, c2 ) ); + return *this; +} + +inline Color& Color::operator*= (float S) +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( this, XMVectorScale( c, S ) ); + return *this; +} + +inline Color& Color::operator/= (const Color& c) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( this ); + XMVECTOR c2 = XMLoadFloat4( &c ); + XMStoreFloat4( this, XMVectorDivide( c1, c2 ) ); + return *this; +} + +//------------------------------------------------------------------------------ +// Urnary operators +//------------------------------------------------------------------------------ + +inline Color Color::operator- () const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + Color R; + XMStoreFloat4( &R, XMVectorNegate( c ) ); + return R; +} + +//------------------------------------------------------------------------------ +// Binary operators +//------------------------------------------------------------------------------ + +inline Color operator+ (const Color& C1, const Color& C2) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( &C1 ); + XMVECTOR c2 = XMLoadFloat4( &C2 ); + Color R; + XMStoreFloat4( &R, XMVectorAdd( c1, c2 ) ); + return R; +} + +inline Color operator- (const Color& C1, const Color& C2) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( &C1 ); + XMVECTOR c2 = XMLoadFloat4( &C2 ); + Color R; + XMStoreFloat4( &R, XMVectorSubtract( c1, c2 ) ); + return R; +} + +inline Color operator* (const Color& C1, const Color& C2) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( &C1 ); + XMVECTOR c2 = XMLoadFloat4( &C2 ); + Color R; + XMStoreFloat4( &R, XMVectorMultiply( c1, c2 ) ); + return R; +} + +inline Color operator* (const Color& C, float S) +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( &C ); + Color R; + XMStoreFloat4( &R, XMVectorScale( c, S ) ); + return R; +} + +inline Color operator/ (const Color& C1, const Color& C2) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( &C1 ); + XMVECTOR c2 = XMLoadFloat4( &C2 ); + Color R; + XMStoreFloat4( &R, XMVectorDivide( c1, c2 ) ); + return R; +} + +inline Color operator* (float S, const Color& C) +{ + using namespace DirectX; + XMVECTOR c1 = XMLoadFloat4( &C ); + Color R; + XMStoreFloat4( &R, XMVectorScale( c1, S ) ); + return R; +} + +//------------------------------------------------------------------------------ +// Color operations +//------------------------------------------------------------------------------ + +inline DirectX::PackedVector::XMCOLOR Color::BGRA() const +{ + using namespace DirectX; + XMVECTOR clr = XMLoadFloat4( this ); + PackedVector::XMCOLOR Packed; + PackedVector::XMStoreColor( &Packed, clr ); + return Packed; +} + +inline DirectX::PackedVector::XMUBYTEN4 Color::RGBA() const +{ + using namespace DirectX; + XMVECTOR clr = XMLoadFloat4( this ); + PackedVector::XMUBYTEN4 Packed; + PackedVector::XMStoreUByteN4( &Packed, clr ); + return Packed; +} + +inline Vector3 Color::ToVector3() const +{ + return Vector3( x, y, z ); +} + +inline Vector4 Color::ToVector4() const +{ + return Vector4( x, y, z, w ); +} + +inline void Color::Negate() +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( this, XMColorNegative( c) ); +} + +inline void Color::Negate( Color& result ) const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMColorNegative( c ) ); +} + +inline void Color::Saturate() +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( this, XMVectorSaturate( c ) ); +} + +inline void Color::Saturate( Color& result ) const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMVectorSaturate( c ) ); +} + +inline void Color::Premultiply() +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMVECTOR a = XMVectorSplatW( c ); + a = XMVectorSelect( g_XMIdentityR3, a, g_XMSelect1110 ); + XMStoreFloat4( this, XMVectorMultiply( c, a ) ); +} + +inline void Color::Premultiply( Color& result ) const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMVECTOR a = XMVectorSplatW( c ); + a = XMVectorSelect( g_XMIdentityR3, a, g_XMSelect1110 ); + XMStoreFloat4( &result, XMVectorMultiply( c, a ) ); +} + +inline void Color::AdjustSaturation( float sat ) +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( this, XMColorAdjustSaturation( c, sat ) ); +} + +inline void Color::AdjustSaturation( float sat, Color& result ) const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMColorAdjustSaturation( c, sat ) ); +} + +inline void Color::AdjustContrast( float contrast ) +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( this, XMColorAdjustContrast( c, contrast ) ); +} + +inline void Color::AdjustContrast( float contrast, Color& result ) const +{ + using namespace DirectX; + XMVECTOR c = XMLoadFloat4( this ); + XMStoreFloat4( &result, XMColorAdjustContrast( c, contrast ) ); +} + +//------------------------------------------------------------------------------ +// Static functions +//------------------------------------------------------------------------------ + +inline void Color::Modulate( const Color& c1, const Color& c2, Color& result ) +{ + using namespace DirectX; + XMVECTOR C0 = XMLoadFloat4( &c1 ); + XMVECTOR C1 = XMLoadFloat4( &c2 ); + XMStoreFloat4( &result, XMColorModulate( C0, C1 ) ); +} + +inline Color Color::Modulate( const Color& c1, const Color& c2 ) +{ + using namespace DirectX; + XMVECTOR C0 = XMLoadFloat4( &c1 ); + XMVECTOR C1 = XMLoadFloat4( &c2 ); + + Color result; + XMStoreFloat4( &result, XMColorModulate( C0, C1 ) ); + return result; +} + +inline void Color::Lerp( const Color& c1, const Color& c2, float t, Color& result ) +{ + using namespace DirectX; + XMVECTOR C0 = XMLoadFloat4( &c1 ); + XMVECTOR C1 = XMLoadFloat4( &c2 ); + XMStoreFloat4( &result, XMVectorLerp( C0, C1, t ) ); +} + +inline Color Color::Lerp( const Color& c1, const Color& c2, float t ) +{ + using namespace DirectX; + XMVECTOR C0 = XMLoadFloat4( &c1 ); + XMVECTOR C1 = XMLoadFloat4( &c2 ); + + Color result; + XMStoreFloat4( &result, XMVectorLerp( C0, C1, t ) ); + return result; +} + + +/**************************************************************************** + * + * Ray + * + ****************************************************************************/ + +//----------------------------------------------------------------------------- +// Comparision operators +//------------------------------------------------------------------------------ +inline bool Ray::operator == ( const Ray& r ) const +{ + using namespace DirectX; + XMVECTOR r1p = XMLoadFloat3( &position ); + XMVECTOR r2p = XMLoadFloat3( &r.position ); + XMVECTOR r1d = XMLoadFloat3( &direction ); + XMVECTOR r2d = XMLoadFloat3( &r.direction ); + return XMVector3Equal( r1p, r2p ) && XMVector3Equal( r1d, r2d ); +} + +inline bool Ray::operator != ( const Ray& r ) const +{ + using namespace DirectX; + XMVECTOR r1p = XMLoadFloat3( &position ); + XMVECTOR r2p = XMLoadFloat3( &r.position ); + XMVECTOR r1d = XMLoadFloat3( &direction ); + XMVECTOR r2d = XMLoadFloat3( &r.direction ); + return XMVector3NotEqual( r1p, r2p ) && XMVector3NotEqual( r1d, r2d ); +} + +//----------------------------------------------------------------------------- +// Ray operators +//------------------------------------------------------------------------------ + +inline bool Ray::Intersects( const BoundingSphere& sphere, _Out_ float& Dist ) const +{ + return sphere.Intersects( position, direction, Dist ); +} + +inline bool Ray::Intersects( const BoundingBox& box, _Out_ float& Dist ) const +{ + return box.Intersects( position, direction, Dist ); +} + +inline bool Ray::Intersects( const Vector3& tri0, const Vector3& tri1, const Vector3& tri2, _Out_ float& Dist ) const +{ + return DirectX::TriangleTests::Intersects( position, direction, tri0, tri1, tri2, Dist ); +} + +inline bool Ray::Intersects( const Plane& plane, _Out_ float& Dist ) const +{ + using namespace DirectX; + + XMVECTOR p = XMLoadFloat4( &plane ); + XMVECTOR dir = XMLoadFloat3( &direction ); + + XMVECTOR nd = XMPlaneDotNormal( p, dir ); + + if ( XMVector3LessOrEqual( XMVectorAbs( nd ), g_RayEpsilon ) ) + { + Dist = 0.f; + return false; + } + else + { + // t = -(dot(n,origin) + D) / dot(n,dir) + XMVECTOR pos = XMLoadFloat3( &position ); + XMVECTOR v = XMPlaneDotNormal( p, pos ); + v = XMVectorAdd( v, XMVectorSplatW(p) ); + v = XMVectorDivide( v, nd ); + float dist = - XMVectorGetX( v ); + if (dist < 0) + { + Dist = 0.f; + return false; + } + else + { + Dist = dist; + return true; + } + } +} + + +/**************************************************************************** + * + * Viewport + * + ****************************************************************************/ + +//------------------------------------------------------------------------------ +// Comparision operators +//------------------------------------------------------------------------------ + +inline bool Viewport::operator == ( const Viewport& vp ) const +{ + return (x == vp.x && y == vp.y + && width == vp.width && height == vp.height + && minDepth == vp.minDepth && maxDepth == vp.maxDepth); +} + +inline bool Viewport::operator != ( const Viewport& vp ) const +{ + return (x != vp.x || y != vp.y + || width != vp.width || height != vp.height + || minDepth != vp.minDepth || maxDepth != vp.maxDepth); +} + +//------------------------------------------------------------------------------ +// Assignment operators +//------------------------------------------------------------------------------ + +inline Viewport& Viewport::operator= (const Viewport& vp) +{ + x = vp.x; y = vp.y; + width = vp.width; height = vp.height; + minDepth = vp.minDepth; maxDepth = vp.maxDepth; + return *this; +} + +inline Viewport& Viewport::operator= (const RECT& rct) +{ + x = float(rct.left); y = float(rct.top); + width = float(rct.right - rct.left); + height = float(rct.bottom - rct.top); + minDepth = 0.f; maxDepth = 1.f; + return *this; +} + +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) +inline Viewport& Viewport::operator= (const D3D11_VIEWPORT& vp) +{ + x = vp.TopLeftX; y = vp.TopLeftY; + width = vp.Width; height = vp.Height; + minDepth = vp.MinDepth; maxDepth = vp.MaxDepth; + return *this; +} +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +inline Viewport& Viewport::operator= (const D3D12_VIEWPORT& vp) +{ + x = vp.TopLeftX; y = vp.TopLeftY; + width = vp.Width; height = vp.Height; + minDepth = vp.MinDepth; maxDepth = vp.MaxDepth; + return *this; +} +#endif + +//------------------------------------------------------------------------------ +// Viewport operations +//------------------------------------------------------------------------------ + +inline float Viewport::AspectRatio() const +{ + if (width == 0.f || height == 0.f) + return 0.f; + + return (width / height); +} + +inline Vector3 Viewport::Project(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world) const +{ + using namespace DirectX; + XMVECTOR v = XMLoadFloat3(&p); + XMMATRIX projection = XMLoadFloat4x4(&proj); + v = XMVector3Project(v, x, y, width, height, minDepth, maxDepth, projection, view, world); + Vector3 result; + XMStoreFloat3(&result, v); + return result; +} + +inline void Viewport::Project(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world, Vector3& result) const +{ + using namespace DirectX; + XMVECTOR v = XMLoadFloat3(&p); + XMMATRIX projection = XMLoadFloat4x4(&proj); + v = XMVector3Project(v, x, y, width, height, minDepth, maxDepth, projection, view, world); + XMStoreFloat3(&result, v); +} + +inline Vector3 Viewport::Unproject(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world) const +{ + using namespace DirectX; + XMVECTOR v = XMLoadFloat3(&p); + XMMATRIX projection = XMLoadFloat4x4(&proj); + v = XMVector3Unproject(v, x, y, width, height, minDepth, maxDepth, projection, view, world); + Vector3 result; + XMStoreFloat3(&result, v); + return result; +} + +inline void Viewport::Unproject(const Vector3& p, const Matrix& proj, const Matrix& view, const Matrix& world, Vector3& result) const +{ + using namespace DirectX; + XMVECTOR v = XMLoadFloat3(&p); + XMMATRIX projection = XMLoadFloat4x4(&proj); + v = XMVector3Unproject(v, x, y, width, height, minDepth, maxDepth, projection, view, world); + XMStoreFloat3(&result, v); +} diff --git a/Kits/DirectXTK12/Inc/SpriteBatch.h b/Kits/DirectXTK12/Inc/SpriteBatch.h new file mode 100644 index 00000000..15e5b4d6 --- /dev/null +++ b/Kits/DirectXTK12/Inc/SpriteBatch.h @@ -0,0 +1,143 @@ +//-------------------------------------------------------------------------------------- +// File: SpriteBatch.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include "RenderTargetState.h" + +namespace DirectX +{ + class ResourceUploadBatch; + + enum SpriteSortMode + { + SpriteSortMode_Deferred, + SpriteSortMode_Immediate, + SpriteSortMode_Texture, + SpriteSortMode_BackToFront, + SpriteSortMode_FrontToBack, + }; + + enum SpriteEffects + { + SpriteEffects_None = 0, + SpriteEffects_FlipHorizontally = 1, + SpriteEffects_FlipVertically = 2, + SpriteEffects_FlipBoth = SpriteEffects_FlipHorizontally | SpriteEffects_FlipVertically, + }; + + class SpriteBatchShaderDescription + { + public: + SpriteBatchShaderDescription( + _In_ ID3D12RootSignature* rootSignature, + _In_ const D3D12_SHADER_BYTECODE* vertexShader, + _In_ const D3D12_SHADER_BYTECODE* pixelShader) + : rootSignature(rootSignature), + vertexShaderByteCode(vertexShader), + pixelShaderByteCode(pixelShader) + { + } + + ID3D12RootSignature* rootSignature; + const D3D12_SHADER_BYTECODE* vertexShaderByteCode; + const D3D12_SHADER_BYTECODE* pixelShaderByteCode; + }; + + class SpriteBatchPipelineStateDescription + { + public: + explicit SpriteBatchPipelineStateDescription( + _In_ const RenderTargetState* renderTarget, + _In_opt_ const D3D12_BLEND_DESC* blend = nullptr, + _In_opt_ const D3D12_DEPTH_STENCIL_DESC* depthStencil = nullptr, + _In_opt_ const D3D12_RASTERIZER_DESC* rasterizer = nullptr, + _In_opt_ const SpriteBatchShaderDescription* shaders = nullptr) + : + blendDesc(blend), + depthStencilDesc(depthStencil), + rasterizerDesc(rasterizer), + renderTargetState(renderTarget), + shaders(shaders) + { + // constructor + } + + const D3D12_BLEND_DESC* blendDesc; + const D3D12_DEPTH_STENCIL_DESC* depthStencilDesc; + const D3D12_RASTERIZER_DESC* rasterizerDesc; + const RenderTargetState* renderTargetState; + const SpriteBatchShaderDescription* shaders; + }; + + class SpriteBatch + { + public: + SpriteBatch(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload, _In_ const SpriteBatchPipelineStateDescription* psoDesc, _In_opt_ const D3D12_VIEWPORT* viewport = nullptr); + SpriteBatch(SpriteBatch&& moveFrom); + SpriteBatch& operator= (SpriteBatch&& moveFrom); + + SpriteBatch(SpriteBatch const&) = delete; + SpriteBatch& operator= (SpriteBatch const&) = delete; + + virtual ~SpriteBatch(); + + // Begin/End a batch of sprite drawing operations. + void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + _In_opt_ SpriteSortMode sortMode = SpriteSortMode_Deferred, + _In_opt_ FXMMATRIX transformMatrix = MatrixIdentity); + void __cdecl End(); + + // Draw overloads specifying position, origin and scale as XMFLOAT2. + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, XMFLOAT2 const& position, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, XMFLOAT2 const& position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + + // Draw overloads specifying position, origin and scale via the first two components of an XMVECTOR. + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, FXMVECTOR position, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, FXMVECTOR position, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + + // Draw overloads specifying position as a RECT. + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, RECT const& destinationRectangle, FXMVECTOR color = Colors::White); + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE textureSRV, _In_ XMUINT2 textureSize, RECT const& destinationRectangle, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0); + + // Rotation mode to be applied to the sprite transformation + void __cdecl SetRotation( DXGI_MODE_ROTATION mode ); + DXGI_MODE_ROTATION __cdecl GetRotation() const; + + // Set viewport for sprite transformation + void __cdecl SetViewport( const D3D12_VIEWPORT& viewPort ); + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + static const XMMATRIX MatrixIdentity; + static const XMFLOAT2 Float2Zero; + }; +} diff --git a/Kits/DirectXTK12/Inc/SpriteFont.h b/Kits/DirectXTK12/Inc/SpriteFont.h new file mode 100644 index 00000000..b9ff434f --- /dev/null +++ b/Kits/DirectXTK12/Inc/SpriteFont.h @@ -0,0 +1,81 @@ +//-------------------------------------------------------------------------------------- +// File: SpriteFont.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "SpriteBatch.h" + + +namespace DirectX +{ + class SpriteFont + { + public: + struct Glyph; + + SpriteFont(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload, _In_z_ wchar_t const* fileName, _In_ D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, _In_ D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor); + SpriteFont(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload, _In_reads_bytes_(dataSize) uint8_t const* dataBlob, _In_ size_t dataSize, _In_ D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, _In_ D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptor); + SpriteFont(_In_ D3D12_GPU_DESCRIPTOR_HANDLE texture, _In_ XMUINT2 textureSize, _In_reads_(glyphCount) Glyph const* glyphs, _In_ size_t glyphCount, _In_ float lineSpacing); + + SpriteFont(SpriteFont&& moveFrom); + SpriteFont& operator= (SpriteFont&& moveFrom); + + SpriteFont(SpriteFont const&) = delete; + SpriteFont& operator= (SpriteFont const&) = delete; + + virtual ~SpriteFont(); + + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color = Colors::White, float rotation = 0, FXMVECTOR origin = g_XMZero, float scale = 1, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + void XM_CALLCONV DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0) const; + + XMVECTOR XM_CALLCONV MeasureString(_In_z_ wchar_t const* text) const; + + RECT __cdecl MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position) const; + RECT XM_CALLCONV MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position) const; + + // Spacing properties + float __cdecl GetLineSpacing() const; + void __cdecl SetLineSpacing(float spacing); + + // Font properties + wchar_t __cdecl GetDefaultCharacter() const; + void __cdecl SetDefaultCharacter(wchar_t character); + + bool __cdecl ContainsCharacter(wchar_t character) const; + + // Custom layout/rendering + Glyph const* __cdecl FindGlyph(wchar_t character) const; + D3D12_GPU_DESCRIPTOR_HANDLE __cdecl GetSpriteSheet() const; + XMUINT2 __cdecl GetSpriteSheetSize() const; + + // Describes a single character glyph. + struct Glyph + { + uint32_t Character; + RECT Subrect; + float XOffset; + float YOffset; + float XAdvance; + }; + + private: + // Private implementation. + class Impl; + + std::unique_ptr pImpl; + + static const XMFLOAT2 Float2Zero; + }; +} diff --git a/Kits/DirectXTK12/Inc/VertexTypes.h b/Kits/DirectXTK12/Inc/VertexTypes.h new file mode 100644 index 00000000..a618fa3c --- /dev/null +++ b/Kits/DirectXTK12/Inc/VertexTypes.h @@ -0,0 +1,285 @@ +//-------------------------------------------------------------------------------------- +// File: VertexTypes.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include + + +namespace DirectX +{ + // Vertex struct holding position information. + struct VertexPosition + { + VertexPosition() = default; + + VertexPosition(XMFLOAT3 const& position) + : position(position) + { } + + VertexPosition(FXMVECTOR position) + { + XMStoreFloat3(&this->position, position); + } + + XMFLOAT3 position; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 1; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and color information. + struct VertexPositionColor + { + VertexPositionColor() = default; + + VertexPositionColor(XMFLOAT3 const& position, XMFLOAT4 const& color) + : position(position), + color(color) + { } + + VertexPositionColor(FXMVECTOR position, FXMVECTOR color) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat4(&this->color, color); + } + + XMFLOAT3 position; + XMFLOAT4 color; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and texture mapping information. + struct VertexPositionTexture + { + VertexPositionTexture() = default; + + VertexPositionTexture(XMFLOAT3 const& position, XMFLOAT2 const& textureCoordinate) + : position(position), + textureCoordinate(textureCoordinate) + { } + + VertexPositionTexture(FXMVECTOR position, FXMVECTOR textureCoordinate) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat2(&this->textureCoordinate, textureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and dual texture mapping information. + struct VertexPositionDualTexture + { + VertexPositionDualTexture() = default; + + VertexPositionDualTexture(XMFLOAT3 const& position, XMFLOAT2 const& textureCoordinate0, XMFLOAT2 const& textureCoordinate1) + : position(position), + textureCoordinate0(textureCoordinate0), + textureCoordinate1(textureCoordinate1) + { } + + VertexPositionDualTexture(FXMVECTOR position, + FXMVECTOR textureCoordinate0, + FXMVECTOR textureCoordinate1) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat2(&this->textureCoordinate0, textureCoordinate0); + XMStoreFloat2(&this->textureCoordinate1, textureCoordinate1); + } + + XMFLOAT3 position; + XMFLOAT2 textureCoordinate0; + XMFLOAT2 textureCoordinate1; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position and normal vector. + struct VertexPositionNormal + { + VertexPositionNormal() = default; + + VertexPositionNormal(XMFLOAT3 const& position, XMFLOAT3 const& normal) + : position(position), + normal(normal) + { } + + VertexPositionNormal(FXMVECTOR position, FXMVECTOR normal) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat3(&this->normal, normal); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 2; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, color, and texture mapping information. + struct VertexPositionColorTexture + { + VertexPositionColorTexture() = default; + + VertexPositionColorTexture(XMFLOAT3 const& position, XMFLOAT4 const& color, XMFLOAT2 const& textureCoordinate) + : position(position), + color(color), + textureCoordinate(textureCoordinate) + { } + + VertexPositionColorTexture(FXMVECTOR position, FXMVECTOR color, FXMVECTOR textureCoordinate) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat4(&this->color, color); + XMStoreFloat2(&this->textureCoordinate, textureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT4 color; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, normal vector, and color information. + struct VertexPositionNormalColor + { + VertexPositionNormalColor() = default; + + VertexPositionNormalColor(XMFLOAT3 const& position, XMFLOAT3 const& normal, XMFLOAT4 const& color) + : position(position), + normal(normal), + color(color) + { } + + VertexPositionNormalColor(FXMVECTOR position, FXMVECTOR normal, FXMVECTOR color) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat3(&this->normal, normal); + XMStoreFloat4(&this->color, color); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT4 color; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, normal vector, and texture mapping information. + struct VertexPositionNormalTexture + { + VertexPositionNormalTexture() = default; + + VertexPositionNormalTexture(XMFLOAT3 const& position, XMFLOAT3 const& normal, XMFLOAT2 const& textureCoordinate) + : position(position), + normal(normal), + textureCoordinate(textureCoordinate) + { } + + VertexPositionNormalTexture(FXMVECTOR position, FXMVECTOR normal, FXMVECTOR textureCoordinate) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat3(&this->normal, normal); + XMStoreFloat2(&this->textureCoordinate, textureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 3; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; + + + // Vertex struct holding position, normal vector, color, and texture mapping information. + struct VertexPositionNormalColorTexture + { + VertexPositionNormalColorTexture() = default; + + VertexPositionNormalColorTexture(XMFLOAT3 const& position, XMFLOAT3 const& normal, XMFLOAT4 const& color, XMFLOAT2 const& textureCoordinate) + : position(position), + normal(normal), + color(color), + textureCoordinate(textureCoordinate) + { } + + VertexPositionNormalColorTexture(FXMVECTOR position, FXMVECTOR normal, FXMVECTOR color, CXMVECTOR textureCoordinate) + { + XMStoreFloat3(&this->position, position); + XMStoreFloat3(&this->normal, normal); + XMStoreFloat4(&this->color, color); + XMStoreFloat2(&this->textureCoordinate, textureCoordinate); + } + + XMFLOAT3 position; + XMFLOAT3 normal; + XMFLOAT4 color; + XMFLOAT2 textureCoordinate; + + static const D3D12_INPUT_LAYOUT_DESC InputLayout; + + private: + static const int InputElementCount = 4; + static const D3D12_INPUT_ELEMENT_DESC InputElements[InputElementCount]; + }; +} diff --git a/Kits/DirectXTK12/Inc/WICTextureLoader.h b/Kits/DirectXTK12/Inc/WICTextureLoader.h new file mode 100644 index 00000000..241949be --- /dev/null +++ b/Kits/DirectXTK12/Inc/WICTextureLoader.h @@ -0,0 +1,78 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader.h +// +// Function for loading a WIC image and creating a Direct3D runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include + + +namespace DirectX +{ + class ResourceUploadBatch; + + // Standard version + HRESULT __cdecl CreateWICTextureFromMemory( + _In_ ID3D12Device* d3dDevice, + _In_ ResourceUploadBatch& resourceUpload, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _Outptr_ ID3D12Resource** texture, + _In_ bool generateMips = true, + _In_ size_t maxsize = 0); + + HRESULT __cdecl CreateWICTextureFromFile( + _In_ ID3D12Device* d3dDevice, + _In_ ResourceUploadBatch& resourceUpload, + _In_z_ const wchar_t* szFileName, + _Outptr_ ID3D12Resource** texture, + _In_ bool generateMips = true, + _In_ size_t maxsize = 0); + + // Extended version + HRESULT __cdecl CreateWICTextureFromMemoryEx( + _In_ ID3D12Device* d3dDevice, + _In_ ResourceUploadBatch& resourceUpload, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool generateMips, + _Outptr_ ID3D12Resource** texture); + + HRESULT __cdecl CreateWICTextureFromFileEx( + _In_ ID3D12Device* d3dDevice, + _In_ ResourceUploadBatch& resourceUpload, + _In_z_ const wchar_t* szFileName, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool generateMips, + _Outptr_ ID3D12Resource** texture); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Readme.txt b/Kits/DirectXTK12/Readme.txt new file mode 100644 index 00000000..6232e95a --- /dev/null +++ b/Kits/DirectXTK12/Readme.txt @@ -0,0 +1,97 @@ +----------------------------------------------- +DirectXTK - the DirectX Tool Kit for DirectX 12 +----------------------------------------------- + +Copyright (c) Microsoft Corporation. All rights reserved. + +June 30, 2016 + +This package contains the "DirectX Tool Kit", a collection of helper classes for +writing Direct3D 12 C++ code for Universal Windows Platform (UWP) apps, Win32 desktop +applications for Windows 10, and Xbox One exclusive apps. + +This code is designed to build with Visual Studio 2015. It is recommended that you +make use of VS 2015 Update 3 and Windows 10 (November 2015) or later. + +Inc\ + Public Header Files (in the DirectX C++ namespace): + + Audio.h - low-level audio API using XAudio2 (DirectXTK for Audio public header) + CommonStates.h - common D3D state combinations + DDSTextureLoader.h - light-weight DDS file texture loader + DescriptorHeap.h - helper for managing DX12 descriptor heaps + DirectXHelpers.h - misc C++ helpers for D3D programming + Effects.h - set of built-in shaders for common rendering tasks + GamePad.h - gamepad controller helper using XInput + GeometricPrimitive.h - draws basic shapes such as cubes and spheres + GraphicsMemory.h - helper for managing dynamic graphics memory allocation + Keyboard.h - keyboard state tracking helper + Model.h - draws meshes loaded from .SDKMESH or .VBO files + Mouse.h - mouse helper + PrimitiveBatch.h - simple and efficient way to draw user primitives + RenderTargetState.h - helper for communicating render target requirements when creating PSOs + ResourceUploadBatch.h - helper for managing texture resource upload to the GPU + ScreenGrab.h - light-weight screen shot saver + SimpleMath.h - simplified C++ wrapper for DirectXMath + SpriteBatch.h - simple & efficient 2D sprite rendering + SpriteFont.h - bitmap based text rendering + VertexTypes.h - structures for commonly used vertex data formats + WICTextureLoader.h - WIC-based image file texture loader + XboxDDSTextureLoader.h - Xbox One exclusive apps variant of DDSTextureLoader + +Src\ + DirectXTK source files and internal implementation headers + +Audio\ + DirectXTK for Audio source files and internal implementation headers + +NOTE: MakeSpriteFont and XWBTool can be found in the DirectX Tool Kit for DirectX 11 package. + +All content and source code for this package are subject to the terms of the MIT License. +. + +Documentation is available at . + +For the latest version of DirectX Tool Kit, bug reports, etc. please visit the project site. + +http://go.microsoft.com/fwlink/?LinkID=615561 + +Note: Xbox One exclusive apps developers using the Xbox One XDK need to generate the + Src\Shaders\Compiled\XboxOne*.inc files to build the library as they are not + included in the distribution package. They are built by running the script + in Src\Shaders - "CompileShaders xbox", and should be generated with the matching + FXC compiler from the Xbox One XDK. While they will continue to work if outdated, + a mismatch will cause runtime compilation overhead that would otherwise be avoided. + +This project has adopted the Microsoft Open Source Code of Conduct. For more information see the +Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments. + +https://opensource.microsoft.com/codeofconduct/ + + +--------------------------------- +COMPARISONS TO DIRECTX 11 VERSION +--------------------------------- + +* No support for loading .CMO models or DGSL effect shaders (i.e. DGSLEffect) + +* VertexTypes does not include VertexPositionNormalTangentColorTexture or + VertexPositionNormalTangentColorTextureSkinning + +* DirectX Tool Kit for DirectX 11 supports Feature Level 9.3, while DirectX 12 requires + Direct3D Feature Level 11.0. There are no expected DirectX 12 drivers for + any lower feature level devices. + +* The library assumes it is building for Windows 10 (aka _WIN32_WINNT=0x0A00) so it makes + use of XAudio 2.9 and WIC2 as well as DirectX 12. + +* DirectX Tool Kit for Audio, GamePad, Keyboard, Mouse, and SimpleMath are identical + to the DirectX 11 version + + +--------------- +RELEASE HISTORY +--------------- + +June 30, 2016 + Original release diff --git a/Kits/DirectXTK12/Src/AlignedNew.h b/Kits/DirectXTK12/Src/AlignedNew.h new file mode 100644 index 00000000..49c761f0 --- /dev/null +++ b/Kits/DirectXTK12/Src/AlignedNew.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// File: AlignedNew.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + + +namespace DirectX +{ + // Derive from this to customize operator new and delete for + // types that have special heap alignment requirements. + // + // Example usage: + // + // __declspec(align(16)) struct MyAlignedType : public AlignedNew + + template + struct AlignedNew + { + // Allocate aligned memory. + static void* operator new (size_t size) + { + const size_t alignment = __alignof(TDerived); + + static_assert(alignment > 8, "AlignedNew is only useful for types with > 8 byte alignment. Did you forget a __declspec(align) on TDerived?"); + + void* ptr = _aligned_malloc(size, alignment); + + if (!ptr) + throw std::bad_alloc(); + + return ptr; + } + + + // Free aligned memory. + static void operator delete (void* ptr) + { + _aligned_free(ptr); + } + + + // Array overloads. + static void* operator new[] (size_t size) + { + return operator new(size); + } + + + static void operator delete[] (void* ptr) + { + operator delete(ptr); + } + }; +} diff --git a/Kits/DirectXTK12/Src/AlphaTestEffect.cpp b/Kits/DirectXTK12/Src/AlphaTestEffect.cpp new file mode 100644 index 00000000..3c0869cc --- /dev/null +++ b/Kits/DirectXTK12/Src/AlphaTestEffect.cpp @@ -0,0 +1,443 @@ +//-------------------------------------------------------------------------------------- +// File: AlphaTestEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" + +using namespace DirectX; + + +// Constant buffer layout. Must match the shader! +struct AlphaTestEffectConstants +{ + XMVECTOR diffuseColor; + XMVECTOR alphaTest; + XMVECTOR fogColor; + XMVECTOR fogVector; + XMMATRIX worldViewProj; +}; + +static_assert( ( sizeof(AlphaTestEffectConstants) % 16 ) == 0, "CB size not padded correctly" ); + + +// Traits type describes our characteristics to the EffectBase template. +struct AlphaTestEffectTraits +{ + typedef AlphaTestEffectConstants ConstantBufferType; + + static const int VertexShaderCount = 4; + static const int PixelShaderCount = 4; + static const int ShaderPermutationCount = 8; +}; + + +// Internal AlphaTestEffect implementation class. +class AlphaTestEffect::Impl : public EffectBase +{ +public: + Impl(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription, D3D12_COMPARISON_FUNC alphaFunction); + + enum DescriptorIndex + { + Texture, + DescriptorCount + }; + + enum RootParameterIndex + { + TextureSRV, + ConstantBuffer, + RootParameterCount + }; + + D3D12_COMPARISON_FUNC mAlphaFunction; + int referenceAlpha; + + bool vertexColorEnabled; + EffectColor color; + + D3D12_GPU_DESCRIPTOR_HANDLE texture; + + int GetCurrentPipelineStatePermutation() const; + + void Apply(_In_ ID3D12GraphicsCommandList* commandList); +}; + + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneAlphaTestEffect_VSAlphaTest.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_VSAlphaTestNoFog.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_VSAlphaTestVc.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_VSAlphaTestVcNoFog.inc" + + #include "Shaders/Compiled/XboxOneAlphaTestEffect_PSAlphaTestLtGt.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_PSAlphaTestLtGtNoFog.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_PSAlphaTestEqNe.inc" + #include "Shaders/Compiled/XboxOneAlphaTestEffect_PSAlphaTestEqNeNoFog.inc" +#else + #include "Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc" + #include "Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc" + #include "Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc" + #include "Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc" + + #include "Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc" + #include "Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc" + #include "Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc" + #include "Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc" +#endif +} + + +const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = +{ + { AlphaTestEffect_VSAlphaTest, sizeof(AlphaTestEffect_VSAlphaTest) }, + { AlphaTestEffect_VSAlphaTestNoFog, sizeof(AlphaTestEffect_VSAlphaTestNoFog) }, + { AlphaTestEffect_VSAlphaTestVc, sizeof(AlphaTestEffect_VSAlphaTestVc) }, + { AlphaTestEffect_VSAlphaTestVcNoFog, sizeof(AlphaTestEffect_VSAlphaTestVcNoFog) }, +}; + + +const int EffectBase::VertexShaderIndices[] = +{ + 0, // lt/gt + 1, // lt/gt, no fog + 2, // lt/gt, vertex color + 3, // lt/gt, vertex color, no fog + + 0, // eq/ne + 1, // eq/ne, no fog + 2, // eq/ne, vertex color + 3, // eq/ne, vertex color, no fog +}; + + +const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = +{ + { AlphaTestEffect_PSAlphaTestLtGt, sizeof(AlphaTestEffect_PSAlphaTestLtGt) }, + { AlphaTestEffect_PSAlphaTestLtGtNoFog, sizeof(AlphaTestEffect_PSAlphaTestLtGtNoFog) }, + { AlphaTestEffect_PSAlphaTestEqNe, sizeof(AlphaTestEffect_PSAlphaTestEqNe) }, + { AlphaTestEffect_PSAlphaTestEqNeNoFog, sizeof(AlphaTestEffect_PSAlphaTestEqNeNoFog) }, +}; + + +const int EffectBase::PixelShaderIndices[] = +{ + 0, // lt/gt + 1, // lt/gt, no fog + 0, // lt/gt, vertex color + 1, // lt/gt, vertex color, no fog + + 2, // eq/ne + 3, // eq/ne, no fog + 2, // eq/ne, vertex color + 3, // eq/ne, vertex color, no fog +}; + + +// Global pool of per-device AlphaTestEffect resources. +SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; + +// Constructor. +AlphaTestEffect::Impl::Impl(_In_ ID3D12Device* device, + int flags, const EffectPipelineStateDescription& pipelineDescription, D3D12_COMPARISON_FUNC alphaFunction) + : EffectBase(device), + mAlphaFunction(alphaFunction), + referenceAlpha(0), + vertexColorEnabled(false) +{ + static_assert( _countof(EffectBase::VertexShaderIndices) == AlphaTestEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::VertexShaderBytecode) == AlphaTestEffectTraits::VertexShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderBytecode) == AlphaTestEffectTraits::PixelShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderIndices) == AlphaTestEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC sampler(0); + CD3DX12_DESCRIPTOR_RANGE descriptorRanges[DescriptorIndex::DescriptorCount]; + descriptorRanges[DescriptorIndex::Texture].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable( + _countof(descriptorRanges), + descriptorRanges); + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, mRootSignature.ReleaseAndGetAddressOf())); + + fog.enabled = (flags & EffectFlags::Fog) != 0; + vertexColorEnabled = (flags & EffectFlags::VertexColor) != 0; + + // overridden alpha test state + D3D12_DEPTH_STENCIL_DESC override = *pipelineDescription.depthStencilDesc; + override.BackFace.StencilFunc = alphaFunction; + override.FrontFace.StencilFunc = alphaFunction; + + int sp = GetCurrentPipelineStatePermutation(); + int vi = EffectBase::VertexShaderIndices[sp]; + int pi = EffectBase::PixelShaderIndices[sp]; + + EffectBase::CreatePipelineState( + mRootSignature.Get(), + pipelineDescription.inputLayout, + &EffectBase::VertexShaderBytecode[vi], + &EffectBase::PixelShaderBytecode[pi], + pipelineDescription.blendDesc, + &override, + pipelineDescription.rasterizerDesc, + pipelineDescription.renderTargetState, + pipelineDescription.primitiveTopology, + pipelineDescription.stripCutValue); +} + + +int AlphaTestEffect::Impl::GetCurrentPipelineStatePermutation() const +{ + int permutation = 0; + + // Use optimized shaders if fog is disabled. + if (!fog.enabled) + { + permutation += 1; + } + + // Support vertex coloring? + if (vertexColorEnabled) + { + permutation += 2; + } + + // Which alpha compare mode? + if (mAlphaFunction == D3D12_COMPARISON_FUNC_EQUAL || + mAlphaFunction == D3D12_COMPARISON_FUNC_NOT_EQUAL) + { + permutation += 4; + } + + return permutation; +} + + +// Sets our state onto the D3D device. +void AlphaTestEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + // Compute derived parameter values. + matrices.SetConstants(dirtyFlags, constants.worldViewProj); + fog.SetConstants(dirtyFlags, matrices.worldView, constants.fogVector); + color.SetConstants(dirtyFlags, constants.diffuseColor); + + UpdateConstants(); + + // Recompute the alpha test settings? + if (dirtyFlags & EffectDirtyFlags::AlphaTest) + { + // Convert reference alpha from 8 bit integer to 0-1 float format. + float reference = (float)referenceAlpha / 255.0f; + + // Comparison tolerance of half the 8 bit integer precision. + const float threshold = 0.5f / 255.0f; + + // What to do if the alpha comparison passes or fails. Positive accepts the pixel, negative clips it. + static const XMVECTORF32 selectIfTrue = { 1, -1 }; + static const XMVECTORF32 selectIfFalse = { -1, 1 }; + static const XMVECTORF32 selectNever = { -1, -1 }; + static const XMVECTORF32 selectAlways = { 1, 1 }; + + float compareTo; + XMVECTOR resultSelector; + + switch (mAlphaFunction) + { + case D3D12_COMPARISON_FUNC_LESS: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = reference - threshold; + resultSelector = selectIfTrue; + break; + + case D3D12_COMPARISON_FUNC_LESS_EQUAL: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = reference + threshold; + resultSelector = selectIfTrue; + break; + + case D3D12_COMPARISON_FUNC_GREATER_EQUAL: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = reference - threshold; + resultSelector = selectIfFalse; + break; + + case D3D12_COMPARISON_FUNC_GREATER: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = reference + threshold; + resultSelector = selectIfFalse; + break; + + case D3D12_COMPARISON_FUNC_EQUAL: + // Shader will evaluate: clip((abs(a - x) < y) ? z : w) + compareTo = reference; + resultSelector = selectIfTrue; + break; + + case D3D12_COMPARISON_FUNC_NOT_EQUAL: + // Shader will evaluate: clip((abs(a - x) < y) ? z : w) + compareTo = reference; + resultSelector = selectIfFalse; + break; + + case D3D12_COMPARISON_FUNC_NEVER: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = 0; + resultSelector = selectNever; + break; + + case D3D12_COMPARISON_FUNC_ALWAYS: + // Shader will evaluate: clip((a < x) ? z : w) + compareTo = 0; + resultSelector = selectAlways; + break; + + default: + throw std::exception("Unknown alpha test function"); + } + + // x = compareTo, y = threshold, zw = resultSelector. + constants.alphaTest = XMVectorPermute<0, 1, 4, 5>(XMVectorSet(compareTo, threshold, 0, 0), resultSelector); + + dirtyFlags &= ~EffectDirtyFlags::AlphaTest; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } + + // Set the root signature + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + + // Set the texture. + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, GetConstantBufferGpuAddress()); + + // Set the pipeline state + commandList->SetPipelineState(EffectBase::mPipelineState.Get()); +} + +// Public constructor. +AlphaTestEffect::AlphaTestEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription, D3D12_COMPARISON_FUNC alphaFunction) + : pImpl(new Impl(device, effectFlags, pipelineDescription, alphaFunction)) +{ +} + + +// Move constructor. +AlphaTestEffect::AlphaTestEffect(AlphaTestEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +AlphaTestEffect& AlphaTestEffect::operator= (AlphaTestEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +AlphaTestEffect::~AlphaTestEffect() +{ +} + + +void AlphaTestEffect::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + pImpl->Apply(commandList); +} + +void XM_CALLCONV AlphaTestEffect::SetWorld(FXMMATRIX value) +{ + pImpl->matrices.world = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV AlphaTestEffect::SetView(FXMMATRIX value) +{ + pImpl->matrices.view = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV AlphaTestEffect::SetProjection(FXMMATRIX value) +{ + pImpl->matrices.projection = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj; +} + + +void XM_CALLCONV AlphaTestEffect::SetDiffuseColor(FXMVECTOR value) +{ + pImpl->color.diffuseColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void AlphaTestEffect::SetAlpha(float value) +{ + pImpl->color.alpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + +void AlphaTestEffect::SetFogStart(float value) +{ + pImpl->fog.start = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void AlphaTestEffect::SetFogEnd(float value) +{ + pImpl->fog.end = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV AlphaTestEffect::SetFogColor(FXMVECTOR value) +{ + pImpl->constants.fogColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void AlphaTestEffect::SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor) +{ + pImpl->texture = srvDescriptor; +} + +void AlphaTestEffect::SetReferenceAlpha(int value) +{ + pImpl->referenceAlpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::AlphaTest; +} diff --git a/Kits/DirectXTK12/Src/BasicEffect.cpp b/Kits/DirectXTK12/Src/BasicEffect.cpp new file mode 100644 index 00000000..5e826f39 --- /dev/null +++ b/Kits/DirectXTK12/Src/BasicEffect.cpp @@ -0,0 +1,601 @@ +//-------------------------------------------------------------------------------------- +// File: BasicEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" +#include "VertexTypes.h" + +using namespace DirectX; + + +// Constant buffer layout. Must match the shader! +struct BasicEffectConstants +{ + XMVECTOR diffuseColor; + XMVECTOR emissiveColor; + XMVECTOR specularColorAndPower; + + XMVECTOR lightDirection[IEffectLights::MaxDirectionalLights]; + XMVECTOR lightDiffuseColor[IEffectLights::MaxDirectionalLights]; + XMVECTOR lightSpecularColor[IEffectLights::MaxDirectionalLights]; + + XMVECTOR eyePosition; + + XMVECTOR fogColor; + XMVECTOR fogVector; + + XMMATRIX world; + XMVECTOR worldInverseTranspose[3]; + XMMATRIX worldViewProj; +}; + +static_assert( ( sizeof(BasicEffectConstants) % 16 ) == 0, "CB size not padded correctly" ); + + +// Traits type describes our characteristics to the EffectBase template. +struct BasicEffectTraits +{ + typedef BasicEffectConstants ConstantBufferType; + + static const int VertexShaderCount = 20; + static const int PixelShaderCount = 10; + static const int ShaderPermutationCount = 32; +}; + + +// Internal BasicEffect implementation class. +class BasicEffect::Impl : public EffectBase +{ +public: + Impl(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription); + + enum DescriptorIndex + { + Texture, + DescriptorCount + }; + + enum RootParameterIndex + { + TextureSRV, + ConstantBuffer, + RootParameterCount + }; + + bool lightingEnabled; + bool preferPerPixelLighting; + bool vertexColorEnabled; + bool textureEnabled; + + D3D12_GPU_DESCRIPTOR_HANDLE texture; + + EffectLights lights; + + int GetCurrentPipelineStatePermutation() const; + + void Apply(_In_ ID3D12GraphicsCommandList* commandList); +}; + + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasic.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicNoFog.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVc.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVcNoFog.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicTxNoFog.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicTxVc.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicTxVcNoFog.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVertexLighting.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVertexLightingVc.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVertexLightingTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicVertexLightingTxVc.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicOneLight.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicOneLightVc.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicOneLightTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicOneLightTxVc.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicPixelLighting.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicPixelLightingVc.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicPixelLightingTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_VSBasicPixelLightingTxVc.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasic.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicNoFog.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicTxNoFog.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicVertexLighting.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicVertexLightingNoFog.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicVertexLightingTx.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicVertexLightingTxNoFog.inc" + + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicPixelLighting.inc" + #include "Shaders/Compiled/XboxOneBasicEffect_PSBasicPixelLightingTx.inc" +#else + #include "Shaders/Compiled/BasicEffect_VSBasic.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicNoFog.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicVc.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicTx.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicTxVc.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc" + + #include "Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc" + + #include "Shaders/Compiled/BasicEffect_VSBasicOneLight.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc" + + #include "Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc" + #include "Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc" + + #include "Shaders/Compiled/BasicEffect_PSBasic.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicNoFog.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicTx.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc" + + #include "Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc" + + #include "Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc" + #include "Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc" +#endif +} + + +const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = +{ + { BasicEffect_VSBasic, sizeof(BasicEffect_VSBasic) }, + { BasicEffect_VSBasicNoFog, sizeof(BasicEffect_VSBasicNoFog) }, + { BasicEffect_VSBasicVc, sizeof(BasicEffect_VSBasicVc) }, + { BasicEffect_VSBasicVcNoFog, sizeof(BasicEffect_VSBasicVcNoFog) }, + { BasicEffect_VSBasicTx, sizeof(BasicEffect_VSBasicTx) }, + { BasicEffect_VSBasicTxNoFog, sizeof(BasicEffect_VSBasicTxNoFog) }, + { BasicEffect_VSBasicTxVc, sizeof(BasicEffect_VSBasicTxVc) }, + { BasicEffect_VSBasicTxVcNoFog, sizeof(BasicEffect_VSBasicTxVcNoFog) }, + + { BasicEffect_VSBasicVertexLighting, sizeof(BasicEffect_VSBasicVertexLighting) }, + { BasicEffect_VSBasicVertexLightingVc, sizeof(BasicEffect_VSBasicVertexLightingVc) }, + { BasicEffect_VSBasicVertexLightingTx, sizeof(BasicEffect_VSBasicVertexLightingTx) }, + { BasicEffect_VSBasicVertexLightingTxVc, sizeof(BasicEffect_VSBasicVertexLightingTxVc) }, + + { BasicEffect_VSBasicOneLight, sizeof(BasicEffect_VSBasicOneLight) }, + { BasicEffect_VSBasicOneLightVc, sizeof(BasicEffect_VSBasicOneLightVc) }, + { BasicEffect_VSBasicOneLightTx, sizeof(BasicEffect_VSBasicOneLightTx) }, + { BasicEffect_VSBasicOneLightTxVc, sizeof(BasicEffect_VSBasicOneLightTxVc) }, + + { BasicEffect_VSBasicPixelLighting, sizeof(BasicEffect_VSBasicPixelLighting) }, + { BasicEffect_VSBasicPixelLightingVc, sizeof(BasicEffect_VSBasicPixelLightingVc) }, + { BasicEffect_VSBasicPixelLightingTx, sizeof(BasicEffect_VSBasicPixelLightingTx) }, + { BasicEffect_VSBasicPixelLightingTxVc, sizeof(BasicEffect_VSBasicPixelLightingTxVc) }, +}; + + +const int EffectBase::VertexShaderIndices[] = +{ + 0, // basic + 1, // no fog + 2, // vertex color + 3, // vertex color, no fog + 4, // texture + 5, // texture, no fog + 6, // texture + vertex color + 7, // texture + vertex color, no fog + + 8, // vertex lighting + 8, // vertex lighting, no fog + 9, // vertex lighting + vertex color + 9, // vertex lighting + vertex color, no fog + 10, // vertex lighting + texture + 10, // vertex lighting + texture, no fog + 11, // vertex lighting + texture + vertex color + 11, // vertex lighting + texture + vertex color, no fog + + 12, // one light + 12, // one light, no fog + 13, // one light + vertex color + 13, // one light + vertex color, no fog + 14, // one light + texture + 14, // one light + texture, no fog + 15, // one light + texture + vertex color + 15, // one light + texture + vertex color, no fog + + 16, // pixel lighting + 16, // pixel lighting, no fog + 17, // pixel lighting + vertex color + 17, // pixel lighting + vertex color, no fog + 18, // pixel lighting + texture + 18, // pixel lighting + texture, no fog + 19, // pixel lighting + texture + vertex color + 19, // pixel lighting + texture + vertex color, no fog +}; + +const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = +{ + { BasicEffect_PSBasic, sizeof(BasicEffect_PSBasic) }, + { BasicEffect_PSBasicNoFog, sizeof(BasicEffect_PSBasicNoFog) }, + { BasicEffect_PSBasicTx, sizeof(BasicEffect_PSBasicTx) }, + { BasicEffect_PSBasicTxNoFog, sizeof(BasicEffect_PSBasicTxNoFog) }, + + { BasicEffect_PSBasicVertexLighting, sizeof(BasicEffect_PSBasicVertexLighting) }, + { BasicEffect_PSBasicVertexLightingNoFog, sizeof(BasicEffect_PSBasicVertexLightingNoFog) }, + { BasicEffect_PSBasicVertexLightingTx, sizeof(BasicEffect_PSBasicVertexLightingTx) }, + { BasicEffect_PSBasicVertexLightingTxNoFog, sizeof(BasicEffect_PSBasicVertexLightingTxNoFog) }, + + { BasicEffect_PSBasicPixelLighting, sizeof(BasicEffect_PSBasicPixelLighting) }, + { BasicEffect_PSBasicPixelLightingTx, sizeof(BasicEffect_PSBasicPixelLightingTx) }, +}; + + +const int EffectBase::PixelShaderIndices[] = +{ + 0, // basic + 1, // no fog + 0, // vertex color + 1, // vertex color, no fog + 2, // texture + 3, // texture, no fog + 2, // texture + vertex color + 3, // texture + vertex color, no fog + + 4, // vertex lighting + 5, // vertex lighting, no fog + 4, // vertex lighting + vertex color + 5, // vertex lighting + vertex color, no fog + 6, // vertex lighting + texture + 7, // vertex lighting + texture, no fog + 6, // vertex lighting + texture + vertex color + 7, // vertex lighting + texture + vertex color, no fog + + 4, // one light + 5, // one light, no fog + 4, // one light + vertex color + 5, // one light + vertex color, no fog + 6, // one light + texture + 7, // one light + texture, no fog + 6, // one light + texture + vertex color + 7, // one light + texture + vertex color, no fog + + 8, // pixel lighting + 8, // pixel lighting, no fog + 8, // pixel lighting + vertex color + 8, // pixel lighting + vertex color, no fog + 9, // pixel lighting + texture + 9, // pixel lighting + texture, no fog + 9, // pixel lighting + texture + vertex color + 9, // pixel lighting + texture + vertex color, no fog +}; + +// Global pool of per-device BasicEffect resources. +SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; + + +// Constructor. +BasicEffect::Impl::Impl(_In_ ID3D12Device* device, int flags, const EffectPipelineStateDescription& pipelineDescription) + : EffectBase(device) +{ + static_assert( _countof(EffectBase::VertexShaderIndices) == BasicEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::VertexShaderBytecode) == BasicEffectTraits::VertexShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderBytecode) == BasicEffectTraits::PixelShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderIndices) == BasicEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + + lights.InitializeConstants(constants.specularColorAndPower, constants.lightDirection, constants.lightDiffuseColor, constants.lightSpecularColor); + + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC sampler(0); + CD3DX12_DESCRIPTOR_RANGE descriptorRanges[DescriptorIndex::DescriptorCount]; + descriptorRanges[DescriptorIndex::Texture].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable( + _countof(descriptorRanges), + descriptorRanges); + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, mRootSignature.ReleaseAndGetAddressOf())); + + fog.enabled = (flags & EffectFlags::Fog) != 0; + lightingEnabled = (flags & EffectFlags::Lighting) != 0; + preferPerPixelLighting = (flags & EffectFlags::PerPixelLighting) != 0; + vertexColorEnabled = (flags & EffectFlags::VertexColor) != 0; + textureEnabled = (flags & EffectFlags::Texture) != 0; + + int sp = GetCurrentPipelineStatePermutation(); + int vi = EffectBase::VertexShaderIndices[sp]; + int pi = EffectBase::PixelShaderIndices[sp]; + + EffectBase::CreatePipelineState( + mRootSignature.Get(), + pipelineDescription.inputLayout, + &EffectBase::VertexShaderBytecode[vi], + &EffectBase::PixelShaderBytecode[pi], + pipelineDescription.blendDesc, + pipelineDescription.depthStencilDesc, + pipelineDescription.rasterizerDesc, + pipelineDescription.renderTargetState, + pipelineDescription.primitiveTopology, + pipelineDescription.stripCutValue); +} + + +int BasicEffect::Impl::GetCurrentPipelineStatePermutation() const +{ + int permutation = 0; + + // Use optimized shaders if fog is disabled. + if (!fog.enabled) + { + permutation += 1; + } + + // Support vertex coloring? + if (vertexColorEnabled) + { + permutation += 2; + } + + // Support texturing? + if (textureEnabled) + { + permutation += 4; + } + + if (lightingEnabled) + { + if (preferPerPixelLighting) + { + // Do lighting in the pixel shader. + permutation += 24; + } + else if (!lights.lightEnabled[1] && !lights.lightEnabled[2]) + { + // Use the only-bother-with-the-first-light shader optimization. + permutation += 16; + } + else + { + // Compute all three lights in the vertex shader. + permutation += 8; + } + } + + return permutation; +} + + +// Sets our state onto the D3D device. +void BasicEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + // Compute derived parameter values. + matrices.SetConstants(dirtyFlags, constants.worldViewProj); + fog.SetConstants(dirtyFlags, matrices.worldView, constants.fogVector); + lights.SetConstants(dirtyFlags, matrices, constants.world, constants.worldInverseTranspose, constants.eyePosition, constants.diffuseColor, constants.emissiveColor, lightingEnabled); + + UpdateConstants(); + + // Set the root signature + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + + // Set the texture descriptors. + // **NOTE** If D3D asserts or crashes here, you probably need to call commandList->SetDescriptorHeaps() with the texture descriptor heap. + if (textureEnabled) + { + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + } + + // Set constants + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, GetConstantBufferGpuAddress()); + + // Set the pipeline state + commandList->SetPipelineState(EffectBase::mPipelineState.Get()); +} + + +// Public constructor. +BasicEffect::BasicEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription) + : pImpl(new Impl(device, effectFlags, pipelineDescription)) +{ +} + + +// Move constructor. +BasicEffect::BasicEffect(BasicEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +BasicEffect& BasicEffect::operator= (BasicEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +BasicEffect::~BasicEffect() +{ +} + + +void BasicEffect::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + pImpl->Apply(commandList); +} + +void XM_CALLCONV BasicEffect::SetWorld(FXMMATRIX value) +{ + pImpl->matrices.world = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV BasicEffect::SetView(FXMMATRIX value) +{ + pImpl->matrices.view = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV BasicEffect::SetProjection(FXMMATRIX value) +{ + pImpl->matrices.projection = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj; +} + + +void XM_CALLCONV BasicEffect::SetDiffuseColor(FXMVECTOR value) +{ + pImpl->lights.diffuseColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV BasicEffect::SetEmissiveColor(FXMVECTOR value) +{ + pImpl->lights.emissiveColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV BasicEffect::SetSpecularColor(FXMVECTOR value) +{ + // Set xyz to new value, but preserve existing w (specular power). + pImpl->constants.specularColorAndPower = XMVectorSelect(pImpl->constants.specularColorAndPower, value, g_XMSelect1110); + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void BasicEffect::SetSpecularPower(float value) +{ + // Set w to new value, but preserve existing xyz (specular color). + pImpl->constants.specularColorAndPower = XMVectorSetW(pImpl->constants.specularColorAndPower, value); + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void BasicEffect::DisableSpecular() +{ + // Set specular color to black, power to 1 + // Note: Don't use a power of 0 or the shader will generate strange highlights on non-specular materials + + pImpl->constants.specularColorAndPower = g_XMIdentityR3; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void BasicEffect::SetAlpha(float value) +{ + pImpl->lights.alpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + +void XM_CALLCONV BasicEffect::SetAmbientLightColor(FXMVECTOR value) +{ + pImpl->lights.ambientLightColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void BasicEffect::SetLightEnabled(int whichLight, bool value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightEnabled(whichLight, value, pImpl->constants.lightDiffuseColor, pImpl->constants.lightSpecularColor); +} + + +void XM_CALLCONV BasicEffect::SetLightDirection(int whichLight, FXMVECTOR value) +{ + EffectLights::ValidateLightIndex(whichLight); + + pImpl->constants.lightDirection[whichLight] = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void XM_CALLCONV BasicEffect::SetLightDiffuseColor(int whichLight, FXMVECTOR value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightDiffuseColor(whichLight, value, pImpl->constants.lightDiffuseColor); +} + + +void XM_CALLCONV BasicEffect::SetLightSpecularColor(int whichLight, FXMVECTOR value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightSpecularColor(whichLight, value, pImpl->constants.lightSpecularColor); +} + + +void BasicEffect::EnableDefaultLighting() +{ + EffectLights::EnableDefaultLighting(this); +} + +void BasicEffect::SetFogStart(float value) +{ + pImpl->fog.start = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void BasicEffect::SetFogEnd(float value) +{ + pImpl->fog.end = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV BasicEffect::SetFogColor(FXMVECTOR value) +{ + pImpl->constants.fogColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void BasicEffect::SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor) +{ + pImpl->texture = srvDescriptor; +} + + diff --git a/Kits/DirectXTK12/Src/Bezier.h b/Kits/DirectXTK12/Src/Bezier.h new file mode 100644 index 00000000..613210a6 --- /dev/null +++ b/Kits/DirectXTK12/Src/Bezier.h @@ -0,0 +1,169 @@ +//-------------------------------------------------------------------------------------- +// File: Bezier.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + + +namespace Bezier +{ + // Performs a cubic bezier interpolation between four control points, + // returning the value at the specified time (t ranges 0 to 1). + // This template implementation can be used to interpolate XMVECTOR, + // float, or any other types that define suitable * and + operators. + template + T CubicInterpolate(T const& p1, T const& p2, T const& p3, T const& p4, float t) + { + using DirectX::operator*; + using DirectX::operator+; + + return p1 * (1 - t) * (1 - t) * (1 - t) + + p2 * 3 * t * (1 - t) * (1 - t) + + p3 * 3 * t * t * (1 - t) + + p4 * t * t * t; + } + + + // Computes the tangent of a cubic bezier curve at the specified time. + // Template supports XMVECTOR, float, or any other types with * and + operators. + template + T CubicTangent(T const& p1, T const& p2, T const& p3, T const& p4, float t) + { + using DirectX::operator*; + using DirectX::operator+; + + return p1 * (-1 + 2 * t - t * t) + + p2 * (1 - 4 * t + 3 * t * t) + + p3 * (2 * t - 3 * t * t) + + p4 * (t * t); + } + + + // Creates vertices for a patch that is tessellated at the specified level. + // Calls the specified outputVertex function for each generated vertex, + // passing the position, normal, and texture coordinate as parameters. + template + void CreatePatchVertices(_In_reads_(16) DirectX::XMVECTOR patch[16], size_t tessellation, bool isMirrored, TOutputFunc outputVertex) + { + using namespace DirectX; + + for (size_t i = 0; i <= tessellation; i++) + { + float u = (float)i / tessellation; + + for (size_t j = 0; j <= tessellation; j++) + { + float v = (float)j / tessellation; + + // Perform four horizontal bezier interpolations + // between the control points of this patch. + XMVECTOR p1 = CubicInterpolate(patch[0], patch[1], patch[2], patch[3], u); + XMVECTOR p2 = CubicInterpolate(patch[4], patch[5], patch[6], patch[7], u); + XMVECTOR p3 = CubicInterpolate(patch[8], patch[9], patch[10], patch[11], u); + XMVECTOR p4 = CubicInterpolate(patch[12], patch[13], patch[14], patch[15], u); + + // Perform a vertical interpolation between the results of the + // previous horizontal interpolations, to compute the position. + XMVECTOR position = CubicInterpolate(p1, p2, p3, p4, v); + + // Perform another four bezier interpolations between the control + // points, but this time vertically rather than horizontally. + XMVECTOR q1 = CubicInterpolate(patch[0], patch[4], patch[8], patch[12], v); + XMVECTOR q2 = CubicInterpolate(patch[1], patch[5], patch[9], patch[13], v); + XMVECTOR q3 = CubicInterpolate(patch[2], patch[6], patch[10], patch[14], v); + XMVECTOR q4 = CubicInterpolate(patch[3], patch[7], patch[11], patch[15], v); + + // Compute vertical and horizontal tangent vectors. + XMVECTOR tangent1 = CubicTangent(p1, p2, p3, p4, v); + XMVECTOR tangent2 = CubicTangent(q1, q2, q3, q4, u); + + // Cross the two tangent vectors to compute the normal. + XMVECTOR normal = XMVector3Cross(tangent1, tangent2); + + if (!XMVector3NearEqual(normal, XMVectorZero(), g_XMEpsilon)) + { + normal = XMVector3Normalize(normal); + + // If this patch is mirrored, we must invert the normal. + if (isMirrored) + { + normal = -normal; + } + } + else + { + // In a tidy and well constructed bezier patch, the preceding + // normal computation will always work. But the classic teapot + // model is not tidy or well constructed! At the top and bottom + // of the teapot, it contains degenerate geometry where a patch + // has several control points in the same place, which causes + // the tangent computation to fail and produce a zero normal. + // We 'fix' these cases by just hard-coding a normal that points + // either straight up or straight down, depending on whether we + // are on the top or bottom of the teapot. This is not a robust + // solution for all possible degenerate bezier patches, but hey, + // it's good enough to make the teapot work correctly! + + normal = XMVectorSelect(g_XMIdentityR1, g_XMNegIdentityR1, XMVectorLess(position, XMVectorZero())); + } + + // Compute the texture coordinate. + float mirroredU = isMirrored ? 1 - u : u; + + XMVECTOR textureCoordinate = XMVectorSet(mirroredU, v, 0, 0); + + // Output this vertex. + outputVertex(position, normal, textureCoordinate); + } + } + } + + + // Creates indices for a patch that is tessellated at the specified level. + // Calls the specified outputIndex function for each generated index value. + template + void CreatePatchIndices(size_t tessellation, bool isMirrored, TOutputFunc outputIndex) + { + size_t stride = tessellation + 1; + + for (size_t i = 0; i < tessellation; i++) + { + for (size_t j = 0; j < tessellation; j++) + { + // Make a list of six index values (two triangles). + std::array indices = + { + i * stride + j, + (i + 1) * stride + j, + (i + 1) * stride + j + 1, + + i * stride + j, + (i + 1) * stride + j + 1, + i * stride + j + 1, + }; + + // If this patch is mirrored, reverse indices to fix the winding order. + if (isMirrored) + { + std::reverse(indices.begin(), indices.end()); + } + + // Output these index values. + std::for_each(indices.begin(), indices.end(), outputIndex); + } + } + } +} diff --git a/Kits/DirectXTK12/Src/BinaryReader.cpp b/Kits/DirectXTK12/Src/BinaryReader.cpp new file mode 100644 index 00000000..c84e1a42 --- /dev/null +++ b/Kits/DirectXTK12/Src/BinaryReader.cpp @@ -0,0 +1,90 @@ +//-------------------------------------------------------------------------------------- +// File: BinaryReader.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "BinaryReader.h" + +using namespace DirectX; + + +// Constructor reads from the filesystem. +BinaryReader::BinaryReader(_In_z_ wchar_t const* fileName) +{ + size_t dataSize; + + HRESULT hr = ReadEntireFile(fileName, mOwnedData, &dataSize); + if ( FAILED(hr) ) + { + DebugTrace( "BinaryReader failed (%08X) to load '%ls'\n", hr, fileName ); + throw std::exception( "BinaryReader" ); + } + + mPos = mOwnedData.get(); + mEnd = mOwnedData.get() + dataSize; +} + + +// Constructor reads from an existing memory buffer. +BinaryReader::BinaryReader(_In_reads_bytes_(dataSize) uint8_t const* dataBlob, size_t dataSize) +{ + mPos = dataBlob; + mEnd = dataBlob + dataSize; +} + + +// Reads from the filesystem into memory. +HRESULT BinaryReader::ReadEntireFile(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr& data, _Out_ size_t* dataSize) +{ + // Open the file. +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(fileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr))); +#endif + + if (!hFile) + return HRESULT_FROM_WIN32(GetLastError()); + + // Get the file size. + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read. + if (fileInfo.EndOfFile.HighPart > 0) + return E_FAIL; + + // Create enough space for the file data. + data.reset(new uint8_t[fileInfo.EndOfFile.LowPart]); + + if (!data) + return E_OUTOFMEMORY; + + // Read the data in. + DWORD bytesRead = 0; + + if (!ReadFile(hFile.get(), data.get(), fileInfo.EndOfFile.LowPart, &bytesRead, nullptr)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (bytesRead < fileInfo.EndOfFile.LowPart) + return E_FAIL; + + *dataSize = bytesRead; + + return S_OK; +} diff --git a/Kits/DirectXTK12/Src/BinaryReader.h b/Kits/DirectXTK12/Src/BinaryReader.h new file mode 100644 index 00000000..2e42cb75 --- /dev/null +++ b/Kits/DirectXTK12/Src/BinaryReader.h @@ -0,0 +1,75 @@ +//-------------------------------------------------------------------------------------- +// File: BinaryReader.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include + +#include "PlatformHelpers.h" + + +namespace DirectX +{ + // Helper for reading binary data, either from the filesystem a memory buffer. + class BinaryReader + { + public: + explicit BinaryReader(_In_z_ wchar_t const* fileName); + BinaryReader(_In_reads_bytes_(dataSize) uint8_t const* dataBlob, size_t dataSize); + + BinaryReader(BinaryReader const&) = delete; + BinaryReader& operator= (BinaryReader const&) = delete; + + // Reads a single value. + template T const& Read() + { + return *ReadArray(1); + } + + + // Reads an array of values. + template T const* ReadArray(size_t elementCount) + { + static_assert(std::is_pod::value, "Can only read plain-old-data types"); + + uint8_t const* newPos = mPos + sizeof(T) * elementCount; + + if (newPos < mPos) + throw std::overflow_error("ReadArray"); + + if (newPos > mEnd) + throw std::exception("End of file"); + + auto result = reinterpret_cast(mPos); + + mPos = newPos; + + return result; + } + + + // Lower level helper reads directly from the filesystem into memory. + static HRESULT ReadEntireFile(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr& data, _Out_ size_t* dataSize); + + + private: + // The data currently being read. + uint8_t const* mPos; + uint8_t const* mEnd; + + std::unique_ptr mOwnedData; + }; +} diff --git a/Kits/DirectXTK12/Src/CommonStates.cpp b/Kits/DirectXTK12/Src/CommonStates.cpp new file mode 100644 index 00000000..b7e3d42e --- /dev/null +++ b/Kits/DirectXTK12/Src/CommonStates.cpp @@ -0,0 +1,320 @@ +//-------------------------------------------------------------------------------------- +// File: CommonStates.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "CommonStates.h" +#include "DirectXHelpers.h" + +using namespace DirectX; + +// -------------------------------------------------------------------------- +// Blend States +// -------------------------------------------------------------------------- + +const D3D12_BLEND_DESC CommonStates::Opaque = +{ + FALSE, // AlphaToCoverageEnable + FALSE, // IndependentBlendEnable + { + FALSE, // BlendEnable + FALSE, // LogicOpEnable + D3D12_BLEND_ONE, // SrcBlend + D3D12_BLEND_ZERO, // DestBlend + D3D12_BLEND_OP_ADD, // BlendOp + D3D12_BLEND_ONE, // SrcBlendAlpha + D3D12_BLEND_ZERO, // DestBlendAlpha + D3D12_BLEND_OP_ADD, // BlendOpAlpha + D3D12_LOGIC_OP_CLEAR, // LogicOp + D3D12_COLOR_WRITE_ENABLE_ALL // RenderTargetWriteMask + } +}; + +const D3D12_BLEND_DESC CommonStates::AlphaBlend = +{ + FALSE, // AlphaToCoverageEnable + FALSE, // IndependentBlendEnable + { + TRUE, // BlendEnable + FALSE, // LogicOpEnable + D3D12_BLEND_ONE, // SrcBlend + D3D12_BLEND_INV_SRC_ALPHA, // DestBlend + D3D12_BLEND_OP_ADD, // BlendOp + D3D12_BLEND_ONE, // SrcBlendAlpha + D3D12_BLEND_INV_SRC_ALPHA, // DestBlendAlpha + D3D12_BLEND_OP_ADD, // BlendOpAlpha + D3D12_LOGIC_OP_CLEAR, // LogicOp + D3D12_COLOR_WRITE_ENABLE_ALL // RenderTargetWriteMask + } +}; + +const D3D12_BLEND_DESC CommonStates::Additive = +{ + FALSE, // AlphaToCoverageEnable + FALSE, // IndependentBlendEnable + { + TRUE, // BlendEnable + FALSE, // LogicOpEnable + D3D12_BLEND_ONE, // SrcBlend + D3D12_BLEND_ONE, // DestBlend + D3D12_BLEND_OP_ADD, // BlendOp + D3D12_BLEND_ONE, // SrcBlendAlpha + D3D12_BLEND_ONE, // DestBlendAlpha + D3D12_BLEND_OP_ADD, // BlendOpAlpha + D3D12_LOGIC_OP_CLEAR, // LogicOp + D3D12_COLOR_WRITE_ENABLE_ALL // RenderTargetWriteMask + } +}; + +const D3D12_BLEND_DESC CommonStates::NonPremultiplied = +{ + FALSE, // AlphaToCoverageEnable + FALSE, // IndependentBlendEnable + { + TRUE, // BlendEnable + FALSE, // LogicOpEnable + D3D12_BLEND_SRC_ALPHA, // SrcBlend + D3D12_BLEND_INV_SRC_ALPHA, // DestBlend + D3D12_BLEND_OP_ADD, // BlendOp + D3D12_BLEND_SRC_ALPHA, // SrcBlendAlpha + D3D12_BLEND_INV_SRC_ALPHA, // DestBlendAlpha + D3D12_BLEND_OP_ADD, // BlendOpAlpha + D3D12_LOGIC_OP_CLEAR, // LogicOp + D3D12_COLOR_WRITE_ENABLE_ALL // RenderTargetWriteMask + } +}; + + +// -------------------------------------------------------------------------- +// Depth-Stencil States +// -------------------------------------------------------------------------- + +const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthNone = +{ + FALSE, // DepthEnable + D3D12_DEPTH_WRITE_MASK_ZERO, // DepthWriteMask + D3D12_COMPARISON_FUNC_ALWAYS, // DepthFunc + FALSE, // StencilEnable + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilReadMask + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilWriteMask + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + }, // FrontFace, + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + } // BackFace +}; + +const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthDefault = +{ + TRUE, // DepthEnable + D3D12_DEPTH_WRITE_MASK_ALL, // DepthWriteMask + D3D12_COMPARISON_FUNC_LESS_EQUAL, // DepthFunc + FALSE, // StencilEnable + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilReadMask + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilWriteMask + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + }, // FrontFace, + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + } // BackFace +}; + +const D3D12_DEPTH_STENCIL_DESC CommonStates::DepthRead = +{ + TRUE, // DepthEnable + D3D12_DEPTH_WRITE_MASK_ZERO, // DepthWriteMask + D3D12_COMPARISON_FUNC_LESS_EQUAL, // DepthFunc + FALSE, // StencilEnable + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilReadMask + D3D12_DEFAULT_STENCIL_READ_MASK, // StencilWriteMask + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + }, // FrontFace, + { + D3D12_STENCIL_OP_KEEP, // StencilFailOp + D3D12_STENCIL_OP_KEEP, // StencilDepthFailOp + D3D12_STENCIL_OP_KEEP, // StencilPassOp + D3D12_COMPARISON_FUNC_ALWAYS // StencilFunc + } // BackFace +}; + + +// -------------------------------------------------------------------------- +// Rasterizer States +// -------------------------------------------------------------------------- + +const D3D12_RASTERIZER_DESC CommonStates::CullNone = +{ + D3D12_FILL_MODE_SOLID, // FillMode + D3D12_CULL_MODE_NONE, // CullMode + FALSE, // FrontCounterClockwise + 0, // DepthBias + 0, // DepthBiasClamp + 0, // SlopeScaledDepthBias + TRUE, // DepthClipEnable + TRUE, // MultisampleEnable + FALSE, // AntialiasedLineEnable + 0, // ForcedSampleCount + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF // ConservativeRaster +}; + +const D3D12_RASTERIZER_DESC CommonStates::CullClockwise = +{ + D3D12_FILL_MODE_SOLID, // FillMode + D3D12_CULL_MODE_FRONT, // CullMode + FALSE, // FrontCounterClockwise + 0, // DepthBias + 0, // DepthBiasClamp + 0, // SlopeScaledDepthBias + TRUE, // DepthClipEnable + TRUE, // MultisampleEnable + FALSE, // AntialiasedLineEnable + 0, // ForcedSampleCount + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF // ConservativeRaster +}; + +const D3D12_RASTERIZER_DESC CommonStates::CullCounterClockwise = +{ + D3D12_FILL_MODE_SOLID, // FillMode + D3D12_CULL_MODE_BACK, // CullMode + FALSE, // FrontCounterClockwise + 0, // DepthBias + 0, // DepthBiasClamp + 0, // SlopeScaledDepthBias + TRUE, // DepthClipEnable + TRUE, // MultisampleEnable + FALSE, // AntialiasedLineEnable + 0, // ForcedSampleCount + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF // ConservativeRaster +}; + +const D3D12_RASTERIZER_DESC CommonStates::Wireframe = +{ + D3D12_FILL_MODE_WIREFRAME, // FillMode + D3D12_CULL_MODE_BACK, // CullMode + FALSE, // FrontCounterClockwise + 0, // DepthBias + 0, // DepthBiasClamp + 0, // SlopeScaledDepthBias + TRUE, // DepthClipEnable + TRUE, // MultisampleEnable + FALSE, // AntialiasedLineEnable + 0, // ForcedSampleCount + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF // ConservativeRaster +}; + + +// -------------------------------------------------------------------------- +// Sampler States +// -------------------------------------------------------------------------- + +const D3D12_SAMPLER_DESC CommonStates::PointWrap = +{ + D3D12_FILTER_MIN_MAG_MIP_POINT, // Filter + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + +const D3D12_SAMPLER_DESC CommonStates::PointClamp = +{ + D3D12_FILTER_MIN_MAG_MIP_POINT, // Filter + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + +const D3D12_SAMPLER_DESC CommonStates::LinearWrap = +{ + D3D12_FILTER_MIN_MAG_MIP_LINEAR, // Filter + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + +const D3D12_SAMPLER_DESC CommonStates::LinearClamp = +{ + D3D12_FILTER_MIN_MAG_MIP_LINEAR, // Filter + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + +const D3D12_SAMPLER_DESC CommonStates::AnisotropicWrap = +{ + D3D12_FILTER_MIN_MAG_MIP_LINEAR, // Filter + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_WRAP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + +const D3D12_SAMPLER_DESC CommonStates::AnisotropicClamp = +{ + D3D12_FILTER_ANISOTROPIC, // Filter + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressU + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressV + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // AddressW + 0, // MipLODBias + D3D12_MAX_MAXANISOTROPY, // MaxAnisotropy + D3D12_COMPARISON_FUNC_NEVER, // ComparisonFunc + { 0, 0, 0, 0 }, // BorderColor + 0, // MinLOD + FLT_MAX // MaxLOD +}; + diff --git a/Kits/DirectXTK12/Src/DDSTextureLoader.cpp b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp new file mode 100644 index 00000000..97a27de3 --- /dev/null +++ b/Kits/DirectXTK12/Src/DDSTextureLoader.cpp @@ -0,0 +1,827 @@ +//-------------------------------------------------------------------------------------- +// File: DDSTextureLoader.cpp +// +// Functions for loading a DDS texture and creating a Direct3D runtime resource for it +// +// Note these functions are useful as a light-weight runtime loader for DDS files. For +// a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "DDSTextureLoader.h" + +#include "dds.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "LoaderHelpers.h" +#include "ResourceUploadBatch.h" + +namespace DirectX +{ + uint32_t CountMips(uint32_t width, uint32_t height); +} + +using namespace DirectX; + +static_assert(DDS_DIMENSION_TEXTURE1D == D3D12_RESOURCE_DIMENSION_TEXTURE1D, "dds mismatch"); +static_assert(DDS_DIMENSION_TEXTURE2D == D3D12_RESOURCE_DIMENSION_TEXTURE2D, "dds mismatch"); +static_assert(DDS_DIMENSION_TEXTURE3D == D3D12_RESOURCE_DIMENSION_TEXTURE3D, "dds mismatch"); + +namespace +{ + + //-------------------------------------------------------------------------------------- + HRESULT FillInitData(_In_ size_t width, + _In_ size_t height, + _In_ size_t depth, + _In_ size_t mipCount, + _In_ size_t arraySize, + _In_ DXGI_FORMAT format, + _In_ size_t maxsize, + _In_ size_t bitSize, + _In_reads_bytes_(bitSize) const uint8_t* bitData, + _Out_ size_t& twidth, + _Out_ size_t& theight, + _Out_ size_t& tdepth, + _Out_ size_t& skipMip, + _Out_writes_(mipCount*arraySize) D3D12_SUBRESOURCE_DATA* initData) + { + if (!bitData || !initData) + { + return E_POINTER; + } + + skipMip = 0; + twidth = 0; + theight = 0; + tdepth = 0; + + size_t NumBytes = 0; + size_t RowBytes = 0; + const uint8_t* pSrcBits = bitData; + const uint8_t* pEndBits = bitData + bitSize; + + size_t index = 0; + for (size_t j = 0; j < arraySize; j++) + { + size_t w = width; + size_t h = height; + size_t d = depth; + for (size_t i = 0; i < mipCount; i++) + { + GetSurfaceInfo(w, + h, + format, + &NumBytes, + &RowBytes, + nullptr + ); + + if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize)) + { + if (!twidth) + { + twidth = w; + theight = h; + tdepth = d; + } + + assert(index < mipCount * arraySize); + _Analysis_assume_(index < mipCount * arraySize); + initData[index].pData = reinterpret_cast(pSrcBits); + initData[index].RowPitch = RowBytes; + initData[index].SlicePitch = NumBytes; + ++index; + } + else if (!j) + { + // Count number of skipped mipmaps (first item only) + ++skipMip; + } + + if (pSrcBits + (NumBytes*d) > pEndBits) + { + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } + + pSrcBits += NumBytes * d; + + w = w >> 1; + h = h >> 1; + d = d >> 1; + if (w == 0) + { + w = 1; + } + if (h == 0) + { + h = 1; + } + if (d == 0) + { + d = 1; + } + } + } + + return (index > 0) ? S_OK : E_FAIL; + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateTextureResource( + _In_ ID3D12Device* d3dDevice, + _In_ D3D12_RESOURCE_DIMENSION resDim, + _In_ size_t width, + _In_ size_t height, + _In_ size_t depth, + _In_ size_t mipCount, + _In_ size_t arraySize, + _In_ DXGI_FORMAT format, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _Outptr_ ID3D12Resource** texture) + { + if (!d3dDevice) + return E_POINTER; + + HRESULT hr = E_FAIL; + + if (forceSRGB) + { + format = MakeSRGB(format); + } + + D3D12_RESOURCE_DESC desc = {}; + desc.Width = static_cast(width); + desc.Height = static_cast(height); + desc.MipLevels = static_cast(mipCount); + desc.DepthOrArraySize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) ? static_cast(depth) : static_cast(arraySize); + desc.Format = format; + desc.Flags = flags; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Dimension = resDim; + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + hr = d3dDevice->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(texture)); + if (SUCCEEDED(hr)) + { + _Analysis_assume_(*texture != 0); + + SetDebugObjectName(*texture, L"DDSTextureLoader"); + } + + return hr; + } + + //-------------------------------------------------------------------------------------- + HRESULT CreateTextureFromDDS(_In_ ID3D12Device* d3dDevice, + _In_ const DDS_HEADER* header, + _In_reads_bytes_(bitSize) const uint8_t* bitData, + _In_ size_t bitSize, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool reserveFullMipChain, + _Outptr_ ID3D12Resource** texture, + _Out_ std::vector& subresources, + _Out_opt_ bool* outIsCubeMap) + { + HRESULT hr = S_OK; + + UINT width = header->width; + UINT height = header->height; + UINT depth = header->depth; + + D3D12_RESOURCE_DIMENSION resDim = D3D12_RESOURCE_DIMENSION_UNKNOWN; + UINT arraySize = 1; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + bool isCubeMap = false; + + size_t mipCount = header->mipMapCount; + if (0 == mipCount) + { + mipCount = 1; + } + + if ((header->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)) + { + auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); + + arraySize = d3d10ext->arraySize; + if (arraySize == 0) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + switch (d3d10ext->dxgiFormat) + { + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + default: + if (BitsPerPixel(d3d10ext->dxgiFormat) == 0) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + + format = d3d10ext->dxgiFormat; + + switch (d3d10ext->resourceDimension) + { + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + // D3DX writes 1D textures with a fixed Height of 1 + if ((header->flags & DDS_HEIGHT) && height != 1) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + height = depth = 1; + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + if (d3d10ext->miscFlag & 0x4 /* RESOURCE_MISC_TEXTURECUBE */) + { + arraySize *= 6; + isCubeMap = true; + } + depth = 1; + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + if (!(header->flags & DDS_HEADER_FLAGS_VOLUME)) + { + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + } + + if (arraySize > 1) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + resDim = static_cast(d3d10ext->resourceDimension); + } + else + { + format = GetDXGIFormat(header->ddspf); + + if (format == DXGI_FORMAT_UNKNOWN) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (header->flags & DDS_HEADER_FLAGS_VOLUME) + { + resDim = D3D12_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { + if (header->caps2 & DDS_CUBEMAP) + { + // We require all six faces to be defined + if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + arraySize = 6; + isCubeMap = true; + } + + depth = 1; + resDim = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture + } + + assert(BitsPerPixel(format) != 0); + } + + // Bound sizes (for security purposes we don't trust DDS file metadata larger than the Direct3D hardware requirements) + if (mipCount > D3D12_REQ_MIP_LEVELS) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + switch (resDim) + { + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + if ((arraySize > D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) || + (width > D3D12_REQ_TEXTURE1D_U_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + if (isCubeMap) + { + // This is the right bound because we set arraySize to (NumCubes*6) above + if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D12_REQ_TEXTURECUBE_DIMENSION) || + (height > D3D12_REQ_TEXTURECUBE_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + } + else if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || + (width > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION) || + (height > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + if ((arraySize > 1) || + (width > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (height > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || + (depth > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + break; + + default: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (outIsCubeMap != nullptr) + { + *outIsCubeMap = isCubeMap; + } + + // Create the texture + std::vector initData; + initData.resize(mipCount * arraySize); + + size_t skipMip = 0; + size_t twidth = 0; + size_t theight = 0; + size_t tdepth = 0; + hr = FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, + twidth, theight, tdepth, skipMip, &initData[0]); + + if (SUCCEEDED(hr)) + { + size_t reservedMips = mipCount; + if (reserveFullMipChain) + { + reservedMips = std::min(D3D12_REQ_MIP_LEVELS, CountMips(width, height)); + } + + hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, reservedMips - skipMip, arraySize, + format, flags, forceSRGB, texture); + + if (FAILED(hr) && !maxsize && (mipCount > 1)) + { + maxsize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D) + ? D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION + : D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + hr = FillInitData(width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData, + twidth, theight, tdepth, skipMip, &initData[0]); + if (SUCCEEDED(hr)) + { + hr = CreateTextureResource(d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize, + format, flags, forceSRGB, texture); + } + } + } + + if (SUCCEEDED(hr)) + { + subresources.insert(subresources.end(), initData.begin(), initData.end()); + } + + return hr; + } +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadDDSTextureFromMemory( + ID3D12Device* d3dDevice, + const uint8_t* ddsData, + size_t ddsDataSize, + ID3D12Resource** texture, + std::vector& subresources, + size_t maxsize, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap) +{ + return LoadDDSTextureFromMemoryEx( + d3dDevice, + ddsData, + ddsDataSize, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + false, + texture, + subresources, + alphaMode, + isCubeMap); +} + + +_Use_decl_annotations_ +HRESULT DirectX::LoadDDSTextureFromMemoryEx( + ID3D12Device* d3dDevice, + const uint8_t* ddsData, + size_t ddsDataSize, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + ID3D12Resource** texture, + std::vector& subresources, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap ) +{ + if ( texture ) + { + *texture = nullptr; + } + if ( alphaMode ) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + if ( isCubeMap ) + { + *isCubeMap = false; + } + + if (!d3dDevice || !ddsData || !texture) + { + return E_INVALIDARG; + } + + // Validate DDS file in memory + if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + { + return E_FAIL; + } + + uint32_t dwMagicNumber = *( const uint32_t* )( ddsData ); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto header = reinterpret_cast( ddsData + sizeof( uint32_t ) ); + + // Verify header to validate DDS file + if (header->size != sizeof(DDS_HEADER) || + header->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for DX10 extension + bool bDXT10Header = false; + if ((header->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC) ) + { + // Must be long enough for both headers and magic value + if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) + { + return E_FAIL; + } + + bDXT10Header = true; + } + + ptrdiff_t offset = sizeof( uint32_t ) + + sizeof( DDS_HEADER ) + + (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0); + + HRESULT hr = CreateTextureFromDDS( d3dDevice, + header, ddsData + offset, ddsDataSize - offset, maxsize, + flags, forceSRGB, reserveFullMipChain, + texture, subresources, isCubeMap ); + if ( SUCCEEDED(hr) ) + { + if (texture != 0 && *texture != 0) + { + SetDebugObjectName(*texture, L"DDSTextureLoader"); + } + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::LoadDDSTextureFromFile( + ID3D12Device* d3dDevice, + const wchar_t* fileName, + ID3D12Resource** texture, + std::unique_ptr& ddsData, + std::vector& subresources, + size_t maxsize, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap ) +{ + return LoadDDSTextureFromFileEx( + d3dDevice, + fileName, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + false, + texture, + ddsData, + subresources, + alphaMode, + isCubeMap ); +} + +_Use_decl_annotations_ +HRESULT DirectX::LoadDDSTextureFromFileEx( + ID3D12Device* d3dDevice, + const wchar_t* fileName, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool reserveFullMipChain, + ID3D12Resource** texture, + std::unique_ptr& ddsData, + std::vector& subresources, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap ) +{ + if ( texture ) + { + *texture = nullptr; + } + if ( alphaMode ) + { + *alphaMode = DDS_ALPHA_MODE_UNKNOWN; + } + if ( isCubeMap ) + { + *isCubeMap = false; + } + + if (!d3dDevice || !fileName || !texture) + { + return E_INVALIDARG; + } + + DDS_HEADER* header = nullptr; + uint8_t* bitData = nullptr; + size_t bitSize = 0; + + HRESULT hr = LoadTextureDataFromFile( fileName, + ddsData, + &header, + &bitData, + &bitSize + ); + if (FAILED(hr)) + { + return hr; + } + + hr = CreateTextureFromDDS( d3dDevice, + header, bitData, bitSize, maxsize, + flags, forceSRGB, reserveFullMipChain, + texture, subresources, isCubeMap ); + + if ( SUCCEEDED(hr) ) + { +#if !defined(NO_D3D12_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + #if defined(_XBOX_ONE) && defined(_TITLE) + if (texture != 0 && *texture != 0) + { + (*texture)->SetName( fileName ); + } + #else + if (texture != 0) + { + CHAR strFileA[MAX_PATH]; + int result = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + fileName, + -1, + strFileA, + MAX_PATH, + nullptr, + FALSE + ); + if ( result > 0 ) + { + const wchar_t* pstrName = wcsrchr(fileName, '\\'); + if (!pstrName) + { + pstrName = fileName; + } + else + { + pstrName++; + } + + if (texture != 0 && *texture != 0) + { + (*texture)->SetName(pstrName); + } + } + } + #endif +#endif + + if ( alphaMode ) + *alphaMode = GetAlphaMode( header ); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateDDSTextureFromMemory( + ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const uint8_t* ddsData, + size_t ddsDataSize, + ID3D12Resource** texture, + bool generateMipsIfMissing, + size_t maxsize, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap) +{ + return CreateDDSTextureFromMemoryEx( + d3dDevice, + resourceUpload, + ddsData, + ddsDataSize, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + generateMipsIfMissing, + texture, + alphaMode, + isCubeMap); +} + + +_Use_decl_annotations_ +HRESULT DirectX::CreateDDSTextureFromMemoryEx( + ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const uint8_t* ddsData, + size_t ddsDataSize, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool generateMipsIfMissing, + ID3D12Resource** texture, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap) +{ + std::vector subresources; + HRESULT hr = LoadDDSTextureFromMemoryEx( + d3dDevice, + ddsData, + ddsDataSize, + maxsize, + flags, + forceSRGB, + generateMipsIfMissing, + texture, + subresources, + alphaMode, + isCubeMap); + + if (SUCCEEDED(hr)) + { + resourceUpload.Upload( + *texture, + 0, + &subresources[0], + (UINT)subresources.size()); + + resourceUpload.Transition( + *texture, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + // If it's missing mips, let's generate them + if (generateMipsIfMissing && subresources.size() != (*texture)->GetDesc().MipLevels) + { + resourceUpload.GenerateMips(*texture); + } + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateDDSTextureFromFile( + ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const wchar_t* fileName, + ID3D12Resource** texture, + bool generateMipsIfMissing, + size_t maxsize, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap) +{ + return CreateDDSTextureFromFileEx( + d3dDevice, + resourceUpload, + fileName, + maxsize, + D3D12_RESOURCE_FLAG_NONE, + false, + generateMipsIfMissing, + texture, + alphaMode, + isCubeMap); +} + +_Use_decl_annotations_ +HRESULT DirectX::CreateDDSTextureFromFileEx( + ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const wchar_t* fileName, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool generateMipsIfMissing, + ID3D12Resource** texture, + DDS_ALPHA_MODE* alphaMode, + bool* isCubeMap) +{ + std::unique_ptr ddsData; + std::vector subresources; + HRESULT hr = LoadDDSTextureFromFileEx( + d3dDevice, + fileName, + maxsize, + flags, + forceSRGB, + generateMipsIfMissing, + texture, + ddsData, + subresources, + alphaMode, + isCubeMap); + + if (SUCCEEDED(hr)) + { + resourceUpload.Upload( + *texture, + 0, + &subresources[0], + (UINT)subresources.size()); + + resourceUpload.Transition( + *texture, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + // If it's missing mips, let's generate them + if (generateMipsIfMissing && subresources.size() != (*texture)->GetDesc().MipLevels) + { + resourceUpload.GenerateMips(*texture); + } + } + + return hr; +} diff --git a/Kits/DirectXTK12/Src/DemandCreate.h b/Kits/DirectXTK12/Src/DemandCreate.h new file mode 100644 index 00000000..9caf052a --- /dev/null +++ b/Kits/DirectXTK12/Src/DemandCreate.h @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------------- +// File: DemandCreate.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "PlatformHelpers.h" + + +namespace DirectX +{ + // Helper for lazily creating a D3D resource. + template + static T* DemandCreate(Microsoft::WRL::ComPtr& comPtr, std::mutex& mutex, TCreateFunc createFunc) + { + T* result = comPtr.Get(); + + // Double-checked lock pattern. + MemoryBarrier(); + + if (!result) + { + std::lock_guard lock(mutex); + + result = comPtr.Get(); + + if (!result) + { + // Create the new object. + ThrowIfFailed( + createFunc(&result) + ); + + MemoryBarrier(); + + comPtr.Attach(result); + } + } + + return result; + } +} diff --git a/Kits/DirectXTK12/Src/DescriptorHeap.cpp b/Kits/DirectXTK12/Src/DescriptorHeap.cpp new file mode 100644 index 00000000..c25102ee --- /dev/null +++ b/Kits/DirectXTK12/Src/DescriptorHeap.cpp @@ -0,0 +1,179 @@ +//-------------------------------------------------------------------------------------- +// File: DescriptorHeap.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "PlatformHelpers.h" +#include "DirectXHelpers.h" +#include "DescriptorHeap.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + struct DescriptorHeapDesc + { + D3D12_DESCRIPTOR_HEAP_TYPE Type; + D3D12_DESCRIPTOR_HEAP_FLAGS Flags; + }; + + static const DescriptorHeapDesc c_DescriptorHeapDescs[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES] = + { + { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }, + { D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }, + { D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE }, + { D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE } + }; +} + +_Use_decl_annotations_ +DescriptorHeap::DescriptorHeap( + ID3D12DescriptorHeap* pExistingHeap) + : m_pHeap(pExistingHeap) +{ + m_hCPU = pExistingHeap->GetCPUDescriptorHandleForHeapStart(); + m_hGPU = pExistingHeap->GetGPUDescriptorHandleForHeapStart(); + m_desc = pExistingHeap->GetDesc(); + + ComPtr device; + pExistingHeap->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); + + m_increment = device->GetDescriptorHandleIncrementSize(m_desc.Type); +} + +_Use_decl_annotations_ +DescriptorHeap::DescriptorHeap( + ID3D12Device* device, + const D3D12_DESCRIPTOR_HEAP_DESC* pDesc) +{ + Create(device, pDesc); +} + +_Use_decl_annotations_ +DescriptorHeap::DescriptorHeap( + ID3D12Device* device, + D3D12_DESCRIPTOR_HEAP_TYPE type, + D3D12_DESCRIPTOR_HEAP_FLAGS flags, + size_t count) +{ + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Flags = flags; + desc.NumDescriptors = static_cast(count); + desc.Type = type; + Create(device, &desc); +} + +_Use_decl_annotations_ +D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors( + ID3D12Device* device, + uint32_t offsetIntoHeap, + uint32_t totalDescriptorCount, + const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts, + const uint32_t* pDescriptorRangeSizes, + uint32_t descriptorRangeCount) +{ + assert(size_t(offsetIntoHeap + totalDescriptorCount) <= size_t(m_desc.NumDescriptors)); + + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = GetCpuHandle(offsetIntoHeap); + + device->CopyDescriptors( + 1, + &cpuHandle, + &totalDescriptorCount, + descriptorRangeCount, + pDescriptorRangeStarts, + pDescriptorRangeSizes, + m_desc.Type); + + auto gpuHandle = GetGpuHandle(offsetIntoHeap); + + return gpuHandle; +} + +_Use_decl_annotations_ +D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors( + ID3D12Device* device, + uint32_t offsetIntoHeap, + const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts, + const uint32_t* pDescriptorRangeSizes, + uint32_t descriptorRangeCount) +{ + uint32_t totalDescriptorCount = 0; + for (uint32_t i = 0; i < descriptorRangeCount; ++i) + totalDescriptorCount += pDescriptorRangeSizes[i]; + + return WriteDescriptors( + device, + offsetIntoHeap, + totalDescriptorCount, + pDescriptorRangeStarts, + pDescriptorRangeSizes, + descriptorRangeCount); +} + +_Use_decl_annotations_ +D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors( + ID3D12Device* device, + uint32_t offsetIntoHeap, + const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptors, + uint32_t descriptorCount) +{ + return WriteDescriptors( + device, + offsetIntoHeap, + descriptorCount, + pDescriptors, + &descriptorCount, + 1); +} + +_Use_decl_annotations_ +void DescriptorHeap::Create( + ID3D12Device* pDevice, + const D3D12_DESCRIPTOR_HEAP_DESC* pDesc ) +{ + assert( pDesc != 0 ); + + m_desc = *pDesc; + m_increment = pDevice->GetDescriptorHandleIncrementSize( pDesc->Type ); + + if (pDesc->NumDescriptors == 0) + { + m_pHeap.Reset(); + m_hCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(D3D12_DEFAULT); + m_hGPU = CD3DX12_GPU_DESCRIPTOR_HANDLE(D3D12_DEFAULT); + } + else + { + ThrowIfFailed( pDevice->CreateDescriptorHeap( + pDesc, + IID_GRAPHICS_PPV_ARGS( m_pHeap.ReleaseAndGetAddressOf() ) ) ); + + m_hCPU = m_pHeap->GetCPUDescriptorHandleForHeapStart(); + + if ( pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE ) + m_hGPU = m_pHeap->GetGPUDescriptorHandleForHeapStart(); + + } +} + +_Use_decl_annotations_ +void DescriptorHeap::DefaultDesc( + D3D12_DESCRIPTOR_HEAP_TYPE type, + D3D12_DESCRIPTOR_HEAP_DESC* pDesc) +{ + assert(c_DescriptorHeapDescs[type].Type == type); + pDesc->Flags = c_DescriptorHeapDescs[type].Flags; + pDesc->NumDescriptors = 0; + pDesc->Type = type; +} diff --git a/Kits/DirectXTK12/Src/DirectXHelpers.cpp b/Kits/DirectXTK12/Src/DirectXHelpers.cpp new file mode 100644 index 00000000..ab857b97 --- /dev/null +++ b/Kits/DirectXTK12/Src/DirectXHelpers.cpp @@ -0,0 +1,99 @@ +//-------------------------------------------------------------------------------------- +// File: DirectXHelpers.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXHelpers.h" +#include "GraphicsMemory.h" + +using namespace DirectX; + +_Use_decl_annotations_ +void DirectX::CreateShaderResourceView( + ID3D12Device* d3dDevice, + ID3D12Resource* tex, + D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, + bool isCubeMap) +{ + D3D12_RESOURCE_DESC desc = tex->GetDesc(); + D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + SRVDesc.Format = desc.Format; + SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + + switch (desc.Dimension) + { + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + { + if (desc.DepthOrArraySize > 1) + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + SRVDesc.Texture1DArray.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + SRVDesc.Texture1DArray.ArraySize = static_cast(desc.DepthOrArraySize); + } + else + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + } + } + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + { + if (isCubeMap) + { + if (desc.DepthOrArraySize > 6) + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; + SRVDesc.TextureCubeArray.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + + // Earlier we set arraySize to (NumCubes * 6) + SRVDesc.TextureCubeArray.NumCubes = static_cast(desc.DepthOrArraySize / 6); + } + else + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + } + } + else if (desc.DepthOrArraySize > 1) + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + SRVDesc.Texture2DArray.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + SRVDesc.Texture2DArray.ArraySize = static_cast(desc.DepthOrArraySize); + } + else + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + } + } + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + { + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MipLevels = (!desc.MipLevels) ? -1 : desc.MipLevels; + } + break; + + case D3D12_RESOURCE_DIMENSION_BUFFER: + throw std::exception("CreateShaderResourceView cannot be used with DIMENSION_BUFFER."); + + default: + throw std::exception("CreateShaderResourceView cannot be used with DIMENSION_UNKNOWN."); + } + + d3dDevice->CreateShaderResourceView(tex, &SRVDesc, srvDescriptor); +} + + diff --git a/Kits/DirectXTK12/Src/DualTextureEffect.cpp b/Kits/DirectXTK12/Src/DualTextureEffect.cpp new file mode 100644 index 00000000..afd87ce4 --- /dev/null +++ b/Kits/DirectXTK12/Src/DualTextureEffect.cpp @@ -0,0 +1,344 @@ +//-------------------------------------------------------------------------------------- +// File: DualTextureEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +// Constant buffer layout. Must match the shader! +struct DualTextureEffectConstants +{ + XMVECTOR diffuseColor; + XMVECTOR fogColor; + XMVECTOR fogVector; + XMMATRIX worldViewProj; +}; + +static_assert( ( sizeof(DualTextureEffectConstants) % 16 ) == 0, "CB size not padded correctly" ); + + +// Traits type describes our characteristics to the EffectBase template. +struct DualTextureEffectTraits +{ + typedef DualTextureEffectConstants ConstantBufferType; + + static const int VertexShaderCount = 4; + static const int PixelShaderCount = 2; + static const int ShaderPermutationCount = 4; +}; + + +// Internal DualTextureEffect implementation class. +class DualTextureEffect::Impl : public EffectBase +{ +public: + Impl(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription); + + enum RootParameterIndex + { + Texture1SRV, + Texture2SRV, + ConstantBuffer, + RootParameterCount + }; + + bool vertexColorEnabled; + EffectColor color; + + D3D12_GPU_DESCRIPTOR_HANDLE texture1; + D3D12_GPU_DESCRIPTOR_HANDLE texture2; + + int GetCurrentPipelineStatePermutation() const; + + void Apply(_In_ ID3D12GraphicsCommandList* commandList); +}; + + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneDualTextureEffect_VSDualTexture.inc" + #include "Shaders/Compiled/XboxOneDualTextureEffect_VSDualTextureNoFog.inc" + #include "Shaders/Compiled/XboxOneDualTextureEffect_VSDualTextureVc.inc" + #include "Shaders/Compiled/XboxOneDualTextureEffect_VSDualTextureVcNoFog.inc" + + #include "Shaders/Compiled/XboxOneDualTextureEffect_PSDualTexture.inc" + #include "Shaders/Compiled/XboxOneDualTextureEffect_PSDualTextureNoFog.inc" +#else + #include "Shaders/Compiled/DualTextureEffect_VSDualTexture.inc" + #include "Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc" + #include "Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc" + #include "Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc" + + #include "Shaders/Compiled/DualTextureEffect_PSDualTexture.inc" + #include "Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc" +#endif +} + + +const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = +{ + { DualTextureEffect_VSDualTexture, sizeof(DualTextureEffect_VSDualTexture) }, + { DualTextureEffect_VSDualTextureNoFog, sizeof(DualTextureEffect_VSDualTextureNoFog) }, + { DualTextureEffect_VSDualTextureVc, sizeof(DualTextureEffect_VSDualTextureVc) }, + { DualTextureEffect_VSDualTextureVcNoFog, sizeof(DualTextureEffect_VSDualTextureVcNoFog) }, + +}; + + +const int EffectBase::VertexShaderIndices[] = +{ + 0, // basic + 1, // no fog + 2, // vertex color + 3, // vertex color, no fog +}; + + +const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = +{ + { DualTextureEffect_PSDualTexture, sizeof(DualTextureEffect_PSDualTexture) }, + { DualTextureEffect_PSDualTextureNoFog, sizeof(DualTextureEffect_PSDualTextureNoFog) }, + +}; + + +const int EffectBase::PixelShaderIndices[] = +{ + 0, // basic + 1, // no fog + 0, // vertex color + 1, // vertex color, no fog +}; + + +// Global pool of per-device DualTextureEffect resources. +SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; + + +// Constructor. +DualTextureEffect::Impl::Impl(_In_ ID3D12Device* device, int flags, const EffectPipelineStateDescription& pipelineDescription) + : EffectBase(device) +{ + static_assert(_countof(EffectBase::VertexShaderIndices) == DualTextureEffectTraits::ShaderPermutationCount, "array/max mismatch"); + static_assert(_countof(EffectBase::VertexShaderBytecode) == DualTextureEffectTraits::VertexShaderCount, "array/max mismatch"); + static_assert(_countof(EffectBase::PixelShaderBytecode) == DualTextureEffectTraits::PixelShaderCount, "array/max mismatch"); + static_assert(_countof(EffectBase::PixelShaderIndices) == DualTextureEffectTraits::ShaderPermutationCount, "array/max mismatch"); + + { // Create Root signature + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC samplers[2]; + samplers[0] = CD3DX12_STATIC_SAMPLER_DESC(0); + samplers[1] = CD3DX12_STATIC_SAMPLER_DESC(1); + + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + + // Texture 1 + CD3DX12_DESCRIPTOR_RANGE descriptorRange1; + descriptorRange1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + rootParameters[RootParameterIndex::Texture1SRV].InitAsDescriptorTable(1, &descriptorRange1); + + // Texture 2 + CD3DX12_DESCRIPTOR_RANGE descriptorRange2; + descriptorRange2.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1); + rootParameters[RootParameterIndex::Texture2SRV].InitAsDescriptorTable(1, &descriptorRange2); + + // Create the root signature + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, _countof(samplers), samplers, rootSignatureFlags); + + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, mRootSignature.ReleaseAndGetAddressOf())); + } + + // Validate flags & state + fog.enabled = (flags & EffectFlags::Fog) != 0; + vertexColorEnabled = (flags & EffectFlags::VertexColor) != 0; + + { // Create pipeline state + int sp = GetCurrentPipelineStatePermutation(); + int vi = EffectBase::VertexShaderIndices[sp]; + int pi = EffectBase::PixelShaderIndices[sp]; + + EffectBase::CreatePipelineState( + mRootSignature.Get(), + pipelineDescription.inputLayout, + &EffectBase::VertexShaderBytecode[vi], + &EffectBase::PixelShaderBytecode[pi], + pipelineDescription.blendDesc, + pipelineDescription.depthStencilDesc, + pipelineDescription.rasterizerDesc, + pipelineDescription.renderTargetState, + pipelineDescription.primitiveTopology, + pipelineDescription.stripCutValue); + } +} + + +int DualTextureEffect::Impl::GetCurrentPipelineStatePermutation() const +{ + int permutation = 0; + + // Use optimized shaders if fog is disabled. + if (!fog.enabled) + { + permutation += 1; + } + + // Support vertex coloring? + if (vertexColorEnabled) + { + permutation += 2; + } + + return permutation; +} + + +// Sets our state onto the D3D device. +void DualTextureEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + // Compute derived parameter values. + matrices.SetConstants(dirtyFlags, constants.worldViewProj); + + fog.SetConstants(dirtyFlags, matrices.worldView, constants.fogVector); + + color.SetConstants(dirtyFlags, constants.diffuseColor); + + UpdateConstants(); + + // Set the root signature + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture1SRV, texture1); + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture2SRV, texture2); + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, GetConstantBufferGpuAddress()); + + // Set the pipeline state + commandList->SetPipelineState(EffectBase::mPipelineState.Get()); +} + + +// Public constructor. +DualTextureEffect::DualTextureEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription) + : pImpl(new Impl(device, effectFlags, pipelineDescription)) +{ +} + + +// Move constructor. +DualTextureEffect::DualTextureEffect(DualTextureEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +DualTextureEffect& DualTextureEffect::operator= (DualTextureEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +DualTextureEffect::~DualTextureEffect() +{ +} + + +void DualTextureEffect::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + pImpl->Apply(commandList); +} + +void XM_CALLCONV DualTextureEffect::SetWorld(FXMMATRIX value) +{ + pImpl->matrices.world = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV DualTextureEffect::SetView(FXMMATRIX value) +{ + pImpl->matrices.view = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV DualTextureEffect::SetProjection(FXMMATRIX value) +{ + pImpl->matrices.projection = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj; +} + + +void XM_CALLCONV DualTextureEffect::SetDiffuseColor(FXMVECTOR value) +{ + pImpl->color.diffuseColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void DualTextureEffect::SetAlpha(float value) +{ + pImpl->color.alpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + +void DualTextureEffect::SetFogStart(float value) +{ + pImpl->fog.start = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void DualTextureEffect::SetFogEnd(float value) +{ + pImpl->fog.end = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV DualTextureEffect::SetFogColor(FXMVECTOR value) +{ + pImpl->constants.fogColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void DualTextureEffect::SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor) +{ + pImpl->texture1 = srvDescriptor; +} + +void DualTextureEffect::SetTexture2(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor) +{ + pImpl->texture2 = srvDescriptor; +} diff --git a/Kits/DirectXTK12/Src/EffectCommon.cpp b/Kits/DirectXTK12/Src/EffectCommon.cpp new file mode 100644 index 00000000..f4be8ffa --- /dev/null +++ b/Kits/DirectXTK12/Src/EffectCommon.cpp @@ -0,0 +1,365 @@ +//-------------------------------------------------------------------------------------- +// File: EffectCommon.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" +#include "DemandCreate.h" +#include "ResourceUploadBatch.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +// Constructor initializes default matrix values. +EffectMatrices::EffectMatrices() +{ + world = XMMatrixIdentity(); + view = XMMatrixIdentity(); + projection = XMMatrixIdentity(); + worldView = XMMatrixIdentity(); +} + + +// Lazily recomputes the combined world+view+projection matrix. +_Use_decl_annotations_ void EffectMatrices::SetConstants(int& dirtyFlags, XMMATRIX& worldViewProjConstant) +{ + if (dirtyFlags & EffectDirtyFlags::WorldViewProj) + { + worldView = XMMatrixMultiply(world, view); + + worldViewProjConstant = XMMatrixTranspose(XMMatrixMultiply(worldView, projection)); + + dirtyFlags &= ~EffectDirtyFlags::WorldViewProj; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } +} + + +// Constructor initializes default fog settings. +EffectFog::EffectFog() +{ + enabled = false; + start = 0; + end = 1; +} + + +// Lazily recomputes the derived vector used by shader fog calculations. +_Use_decl_annotations_ +void XM_CALLCONV EffectFog::SetConstants(int& dirtyFlags, FXMMATRIX worldView, XMVECTOR& fogVectorConstant) +{ + if (enabled) + { + if (dirtyFlags & (EffectDirtyFlags::FogVector | EffectDirtyFlags::FogEnable)) + { + if (start == end) + { + // Degenerate case: force everything to 100% fogged if start and end are the same. + static const XMVECTORF32 fullyFogged = { 0, 0, 0, 1 }; + + fogVectorConstant = fullyFogged; + } + else + { + // We want to transform vertex positions into view space, take the resulting + // Z value, then scale and offset according to the fog start/end distances. + // Because we only care about the Z component, the shader can do all this + // with a single dot product, using only the Z row of the world+view matrix. + + // _13, _23, _33, _43 + XMVECTOR worldViewZ = XMVectorMergeXY(XMVectorMergeZW(worldView.r[0], worldView.r[2]), + XMVectorMergeZW(worldView.r[1], worldView.r[3])); + + // 0, 0, 0, fogStart + XMVECTOR wOffset = XMVectorSwizzle<1, 2, 3, 0>(XMLoadFloat(&start)); + + fogVectorConstant = (worldViewZ + wOffset) / (start - end); + } + + dirtyFlags &= ~(EffectDirtyFlags::FogVector | EffectDirtyFlags::FogEnable); + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } + } + else + { + // When fog is disabled, make sure the fog vector is reset to zero. + if (dirtyFlags & EffectDirtyFlags::FogEnable) + { + fogVectorConstant = g_XMZero; + + dirtyFlags &= ~EffectDirtyFlags::FogEnable; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } + } +} + + +// Constructor initializes default material color settings. +EffectColor::EffectColor() +{ + diffuseColor = g_XMOne; + alpha = 1; +} + + +// Lazily recomputes the material color parameter for shaders that do not support realtime lighting. +void EffectColor::SetConstants(_Inout_ int& dirtyFlags, _Inout_ XMVECTOR& diffuseColorConstant) +{ + if (dirtyFlags & EffectDirtyFlags::MaterialColor) + { + XMVECTOR alphaVector = XMVectorReplicate(alpha); + + // xyz = diffuse * alpha, w = alpha. + diffuseColorConstant = XMVectorSelect(alphaVector, diffuseColor * alphaVector, g_XMSelect1110); + + dirtyFlags &= ~EffectDirtyFlags::MaterialColor; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } +} + + +// Constructor initializes default light settings. +EffectLights::EffectLights() +{ + emissiveColor = g_XMZero; + ambientLightColor = g_XMZero; + + for (int i = 0; i < MaxDirectionalLights; i++) + { + lightEnabled[i] = (i == 0); + lightDiffuseColor[i] = g_XMOne; + lightSpecularColor[i] = g_XMZero; + } +} + + +#pragma prefast(push) +#pragma prefast(disable:22103, "PREFAST doesn't understand buffer is bounded by a static const value even with SAL" ) + +// Initializes constant buffer fields to match the current lighting state. +_Use_decl_annotations_ void EffectLights::InitializeConstants(XMVECTOR& specularColorAndPowerConstant, XMVECTOR* lightDirectionConstant, XMVECTOR* lightDiffuseConstant, XMVECTOR* lightSpecularConstant) +{ + static const XMVECTORF32 defaultSpecular = { 1, 1, 1, 16 }; + static const XMVECTORF32 defaultLightDirection = { 0, -1, 0, 0 }; + + specularColorAndPowerConstant = defaultSpecular; + + for (int i = 0; i < MaxDirectionalLights; i++) + { + lightDirectionConstant[i] = defaultLightDirection; + + lightDiffuseConstant[i] = lightEnabled[i] ? lightDiffuseColor[i] : g_XMZero; + lightSpecularConstant[i] = lightEnabled[i] ? lightSpecularColor[i] : g_XMZero; + } +} + +#pragma prefast(pop) + + +// Lazily recomputes derived parameter values used by shader lighting calculations. +_Use_decl_annotations_ void EffectLights::SetConstants(int& dirtyFlags, EffectMatrices const& matrices, XMMATRIX& worldConstant, XMVECTOR worldInverseTransposeConstant[3], XMVECTOR& eyePositionConstant, XMVECTOR& diffuseColorConstant, XMVECTOR& emissiveColorConstant, bool lightingEnabled) +{ + if (lightingEnabled) + { + // World inverse transpose matrix. + if (dirtyFlags & EffectDirtyFlags::WorldInverseTranspose) + { + worldConstant = XMMatrixTranspose(matrices.world); + + XMMATRIX worldInverse = XMMatrixInverse(nullptr, matrices.world); + + worldInverseTransposeConstant[0] = worldInverse.r[0]; + worldInverseTransposeConstant[1] = worldInverse.r[1]; + worldInverseTransposeConstant[2] = worldInverse.r[2]; + + dirtyFlags &= ~EffectDirtyFlags::WorldInverseTranspose; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } + + // Eye position vector. + if (dirtyFlags & EffectDirtyFlags::EyePosition) + { + XMMATRIX viewInverse = XMMatrixInverse(nullptr, matrices.view); + + eyePositionConstant = viewInverse.r[3]; + + dirtyFlags &= ~EffectDirtyFlags::EyePosition; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } + } + + // Material color parameters. The desired lighting model is: + // + // ((ambientLightColor + sum(diffuse directional light)) * diffuseColor) + emissiveColor + // + // When lighting is disabled, ambient and directional lights are ignored, leaving: + // + // diffuseColor + emissiveColor + // + // For the lighting disabled case, we can save one shader instruction by precomputing + // diffuse+emissive on the CPU, after which the shader can use diffuseColor directly, + // ignoring its emissive parameter. + // + // When lighting is enabled, we can merge the ambient and emissive settings. If we + // set our emissive parameter to emissive+(ambient*diffuse), the shader no longer + // needs to bother adding the ambient contribution, simplifying its computation to: + // + // (sum(diffuse directional light) * diffuseColor) + emissiveColor + // + // For futher optimization goodness, we merge material alpha with the diffuse + // color parameter, and premultiply all color values by this alpha. + + if (dirtyFlags & EffectDirtyFlags::MaterialColor) + { + XMVECTOR diffuse = diffuseColor; + XMVECTOR alphaVector = XMVectorReplicate(alpha); + + if (lightingEnabled) + { + // Merge emissive and ambient light contributions. + emissiveColorConstant = (emissiveColor + ambientLightColor * diffuse) * alphaVector; + } + else + { + // Merge diffuse and emissive light contributions. + diffuse += emissiveColor; + } + + // xyz = diffuse * alpha, w = alpha. + diffuseColorConstant = XMVectorSelect(alphaVector, diffuse * alphaVector, g_XMSelect1110); + + dirtyFlags &= ~EffectDirtyFlags::MaterialColor; + dirtyFlags |= EffectDirtyFlags::ConstantBuffer; + } +} + + +#pragma prefast(push) +#pragma prefast(disable:26015, "PREFAST doesn't understand that ValidateLightIndex bounds whichLight" ) + +// Helper for turning one of the directional lights on or off. +_Use_decl_annotations_ int EffectLights::SetLightEnabled(int whichLight, bool value, XMVECTOR* lightDiffuseConstant, XMVECTOR* lightSpecularConstant) +{ + ValidateLightIndex(whichLight); + + if (lightEnabled[whichLight] == value) + return 0; + + lightEnabled[whichLight] = value; + + if (value) + { + // If this light is now on, store its color in the constant buffer. + lightDiffuseConstant[whichLight] = lightDiffuseColor[whichLight]; + lightSpecularConstant[whichLight] = lightSpecularColor[whichLight]; + } + else + { + // If the light is off, reset constant buffer colors to zero. + lightDiffuseConstant[whichLight] = g_XMZero; + lightSpecularConstant[whichLight] = g_XMZero; + } + + return EffectDirtyFlags::ConstantBuffer; +} + + +// Helper for setting diffuse color of one of the directional lights. +_Use_decl_annotations_ +int XM_CALLCONV EffectLights::SetLightDiffuseColor(int whichLight, FXMVECTOR value, XMVECTOR* lightDiffuseConstant) +{ + ValidateLightIndex(whichLight); + + // Locally store the new color. + lightDiffuseColor[whichLight] = value; + + // If this light is currently on, also update the constant buffer. + if (lightEnabled[whichLight]) + { + lightDiffuseConstant[whichLight] = value; + + return EffectDirtyFlags::ConstantBuffer; + } + + return 0; +} + + +// Helper for setting specular color of one of the directional lights. +_Use_decl_annotations_ +int XM_CALLCONV EffectLights::SetLightSpecularColor(int whichLight, FXMVECTOR value, XMVECTOR* lightSpecularConstant) +{ + ValidateLightIndex(whichLight); + + // Locally store the new color. + lightSpecularColor[whichLight] = value; + + // If this light is currently on, also update the constant buffer. + if (lightEnabled[whichLight]) + { + lightSpecularConstant[whichLight] = value; + + return EffectDirtyFlags::ConstantBuffer; + } + + return 0; +} + +#pragma prefast(pop) + + +// Parameter validation helper. +void EffectLights::ValidateLightIndex(int whichLight) +{ + if (whichLight < 0 || whichLight >= MaxDirectionalLights) + { + throw std::out_of_range("whichLight parameter out of range"); + } +} + + +// Activates the default lighting rig (key, fill, and back lights). +void EffectLights::EnableDefaultLighting(_In_ IEffectLights* effect) +{ + static const XMVECTORF32 defaultDirections[MaxDirectionalLights] = + { + { -0.5265408f, -0.5735765f, -0.6275069f }, + { 0.7198464f, 0.3420201f, 0.6040227f }, + { 0.4545195f, -0.7660444f, 0.4545195f }, + }; + + static const XMVECTORF32 defaultDiffuse[MaxDirectionalLights] = + { + { 1.0000000f, 0.9607844f, 0.8078432f }, + { 0.9647059f, 0.7607844f, 0.4078432f }, + { 0.3231373f, 0.3607844f, 0.3937255f }, + }; + + static const XMVECTORF32 defaultSpecular[MaxDirectionalLights] = + { + { 1.0000000f, 0.9607844f, 0.8078432f }, + { 0.0000000f, 0.0000000f, 0.0000000f }, + { 0.3231373f, 0.3607844f, 0.3937255f }, + }; + + static const XMVECTORF32 defaultAmbient = { 0.05333332f, 0.09882354f, 0.1819608f }; + + effect->SetAmbientLightColor(defaultAmbient); + + for (int i = 0; i < MaxDirectionalLights; i++) + { + effect->SetLightEnabled(i, true); + effect->SetLightDirection(i, defaultDirections[i]); + effect->SetLightDiffuseColor(i, defaultDiffuse[i]); + effect->SetLightSpecularColor(i, defaultSpecular[i]); + } +} diff --git a/Kits/DirectXTK12/Src/EffectCommon.h b/Kits/DirectXTK12/Src/EffectCommon.h new file mode 100644 index 00000000..d4185d8d --- /dev/null +++ b/Kits/DirectXTK12/Src/EffectCommon.h @@ -0,0 +1,255 @@ +//-------------------------------------------------------------------------------------- +// File: EffectCommon.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include + +#include "Effects.h" +#include "PlatformHelpers.h" +#include "SharedResourcePool.h" +#include "AlignedNew.h" +#include "DescriptorHeap.h" +#include "GraphicsMemory.h" +#include "DirectXHelpers.h" +#include "RenderTargetState.h" + +// BasicEffect, SkinnedEffect, et al, have many things in common, but also significant +// differences (for instance, not all the effects support lighting). This header breaks +// out common functionality into a set of helpers which can be assembled in different +// combinations to build up whatever subset is needed by each effect. + + +namespace DirectX +{ + // Bitfield tracks which derived parameter values need to be recomputed. + namespace EffectDirtyFlags + { + const int ConstantBuffer = 0x01; + const int WorldViewProj = 0x02; + const int WorldInverseTranspose = 0x04; + const int EyePosition = 0x08; + const int MaterialColor = 0x10; + const int FogVector = 0x20; + const int FogEnable = 0x40; + const int AlphaTest = 0x80; + } + + // Helper stores matrix parameter values, and computes derived matrices. + struct EffectMatrices + { + EffectMatrices(); + + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + XMMATRIX worldView; + + void SetConstants(_Inout_ int& dirtyFlags, _Inout_ XMMATRIX& worldViewProjConstant); + }; + + + // Helper stores the current fog settings, and computes derived shader parameters. + struct EffectFog + { + EffectFog(); + + bool enabled; + float start; + float end; + + void XM_CALLCONV SetConstants(_Inout_ int& dirtyFlags, _In_ FXMMATRIX worldView, _Inout_ XMVECTOR& fogVectorConstant); + }; + + + // Helper stores material color settings, and computes derived parameters for shaders that do not support realtime lighting. + struct EffectColor + { + EffectColor(); + + XMVECTOR diffuseColor; + float alpha; + + void SetConstants(_Inout_ int& dirtyFlags, _Inout_ XMVECTOR& diffuseColorConstant); + }; + + + // Helper stores the current light settings, and computes derived shader parameters. + struct EffectLights : public EffectColor + { + EffectLights(); + + static const int MaxDirectionalLights = IEffectLights::MaxDirectionalLights; + + + // Fields. + XMVECTOR emissiveColor; + XMVECTOR ambientLightColor; + + bool lightEnabled[MaxDirectionalLights]; + XMVECTOR lightDiffuseColor[MaxDirectionalLights]; + XMVECTOR lightSpecularColor[MaxDirectionalLights]; + + + // Methods. + void InitializeConstants(_Out_ XMVECTOR& specularColorAndPowerConstant, _Out_writes_all_(MaxDirectionalLights) XMVECTOR* lightDirectionConstant, _Out_writes_all_(MaxDirectionalLights) XMVECTOR* lightDiffuseConstant, _Out_writes_all_(MaxDirectionalLights) XMVECTOR* lightSpecularConstant); + void SetConstants(_Inout_ int& dirtyFlags, _In_ EffectMatrices const& matrices, _Inout_ XMMATRIX& worldConstant, _Inout_updates_(3) XMVECTOR worldInverseTransposeConstant[3], _Inout_ XMVECTOR& eyePositionConstant, _Inout_ XMVECTOR& diffuseColorConstant, _Inout_ XMVECTOR& emissiveColorConstant, bool lightingEnabled); + + int SetLightEnabled(int whichLight, bool value, _Inout_updates_(MaxDirectionalLights) XMVECTOR* lightDiffuseConstant, _Inout_updates_(MaxDirectionalLights) XMVECTOR* lightSpecularConstant); + int XM_CALLCONV SetLightDiffuseColor(int whichLight, FXMVECTOR value, _Inout_updates_(MaxDirectionalLights) XMVECTOR* lightDiffuseConstant); + int XM_CALLCONV SetLightSpecularColor(int whichLight, FXMVECTOR value, _Inout_updates_(MaxDirectionalLights) XMVECTOR* lightSpecularConstant); + + static void ValidateLightIndex(int whichLight); + static void EnableDefaultLighting(_In_ IEffectLights* effect); + }; + + // Factory for lazily instantiating shaders. BasicEffect supports many different + // shader permutations, so we only bother creating the ones that are actually used. + class EffectDeviceResources + { + public: + EffectDeviceResources(_In_ ID3D12Device* device) + : mDevice(device) + { } + + inline ID3D12Device* GetDevice() { return mDevice.Get(); } + + protected: + Microsoft::WRL::ComPtr mDevice; + Microsoft::WRL::ComPtr mDefaultTexture; + + std::mutex mMutex; + }; + + // Templated base class provides functionality common to all the built-in effects. + template + class EffectBase : public AlignedNew + { + public: + typename Traits::ConstantBufferType constants; + + // Constructor. + EffectBase(_In_ ID3D12Device* device) + : dirtyFlags(INT_MAX), + mDeviceResources(deviceResourcesPool.DemandCreate(device)), + constants{} + { + // Initialize the constant buffer data + mConstantBuffer = GraphicsMemory::Get().AllocateConstant(constants); + } + + // Commits constants to the constant buffer memory + void UpdateConstants() + { + // Make sure the constant buffer is up to date. + if (dirtyFlags & EffectDirtyFlags::ConstantBuffer) + { + mConstantBuffer = GraphicsMemory::Get().AllocateConstant(constants); + + dirtyFlags &= ~EffectDirtyFlags::ConstantBuffer; + } + } + + D3D12_GPU_VIRTUAL_ADDRESS GetConstantBufferGpuAddress() + { + return mConstantBuffer.GpuAddress(); + } + + void CreatePipelineState( + _In_ ID3D12RootSignature* rootSignature, + _In_ const D3D12_INPUT_LAYOUT_DESC* inputLayout, + _In_ const D3D12_SHADER_BYTECODE* vertexShaderByteCode, + _In_ const D3D12_SHADER_BYTECODE* pixelShaderByteCode, + _In_ const D3D12_BLEND_DESC* blend, + _In_ const D3D12_DEPTH_STENCIL_DESC* depthStencil, + _In_ const D3D12_RASTERIZER_DESC* rasterizer, + _In_ const RenderTargetState* renderTarget, + _In_ D3D12_PRIMITIVE_TOPOLOGY_TYPE primitiveTopology, + _In_ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE stripCutValue) + { + ID3D12Device* device = mDeviceResources->GetDevice(); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = rootSignature; + psoDesc.BlendState = *blend; + psoDesc.DepthStencilState = *depthStencil; + psoDesc.RasterizerState = *rasterizer; + psoDesc.DSVFormat = renderTarget->dsvFormat; + psoDesc.NodeMask = renderTarget->nodeMask; + psoDesc.NumRenderTargets = renderTarget->numRenderTargets; + memcpy(psoDesc.RTVFormats, renderTarget->rtvFormats, sizeof(psoDesc.RTVFormats)); + psoDesc.SampleDesc = renderTarget->sampleDesc; + psoDesc.SampleMask = renderTarget->sampleMask; + psoDesc.InputLayout = *inputLayout; + psoDesc.IBStripCutValue = stripCutValue; + psoDesc.PrimitiveTopologyType = primitiveTopology; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + psoDesc.VS = *vertexShaderByteCode; + psoDesc.PS = *pixelShaderByteCode; + + HRESULT hr = device->CreateGraphicsPipelineState( + &psoDesc, + IID_GRAPHICS_PPV_ARGS(mPipelineState.ReleaseAndGetAddressOf())); + + + if (FAILED(hr)) + { + throw std::exception( + "CreatePipelineState failed to create a PSO. " + "Enable the Direct3D Debug Layer for more information."); + } + } + + ID3D12Device* GetDevice() { return mDeviceResources->GetDevice(); } + + // Fields. + EffectMatrices matrices; + EffectFog fog; + int dirtyFlags; + + protected: + // Static arrays hold all the precompiled shader permutations. + static const D3D12_SHADER_BYTECODE VertexShaderBytecode[Traits::VertexShaderCount]; + static const D3D12_SHADER_BYTECODE PixelShaderBytecode[Traits::PixelShaderCount]; + // .. and shader entry points + static const int VertexShaderIndices[Traits::ShaderPermutationCount]; + static const int PixelShaderIndices[Traits::ShaderPermutationCount]; + // ... and vertex layout tables + static const D3D12_INPUT_LAYOUT_DESC VertexShaderInputLayouts[Traits::ShaderPermutationCount]; + + // Per instance cache of PSOs, populated with variants for each shader & layout + Microsoft::WRL::ComPtr mPipelineState; + + // Per instance root signature (this could possibly be per effect type) + Microsoft::WRL::ComPtr mRootSignature; + + private: + // D3D constant buffer holds a copy of the same data as the public 'constants' field. + GraphicsResource mConstantBuffer; + + // Only one of these helpers is allocated per D3D device, even if there are multiple effect instances. + class DeviceResources : public EffectDeviceResources + { + public: + DeviceResources(_In_ ID3D12Device* device) + : EffectDeviceResources(device) + { } + }; + + // Per-device resources. + std::shared_ptr mDeviceResources; + + static SharedResourcePool deviceResourcesPool; + }; +} diff --git a/Kits/DirectXTK12/Src/EffectFactory.cpp b/Kits/DirectXTK12/Src/EffectFactory.cpp new file mode 100644 index 00000000..df28d998 --- /dev/null +++ b/Kits/DirectXTK12/Src/EffectFactory.cpp @@ -0,0 +1,389 @@ +//-------------------------------------------------------------------------------------- +// File: EffectFactory.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Effects.h" +#include "CommonStates.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" + +#include + + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +// Internal EffectFactory implementation class. Only one of these helpers is allocated +// per D3D device, even if there are multiple public facing EffectFactory instances. +class EffectFactory::Impl +{ +public: + Impl(_In_ ID3D12Device* device, _In_ ID3D12DescriptorHeap* heap) + : device(device) + , mDescriptors(heap) + , mSharing(true) + { + } + + std::shared_ptr CreateEffect( + _In_ const EffectInfo& info, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ const D3D12_INPUT_LAYOUT_DESC& inputLayout, + _In_opt_ int baseDescriptorOffset); + + void ReleaseCache(); + void SetSharing( bool enabled ) { mSharing = enabled; } + + ComPtr mDescriptors; + +private: + ID3D12Device* device; + + typedef std::map< std::wstring, std::shared_ptr > EffectCache; + + EffectCache mEffectCache; + EffectCache mEffectCacheSkinning; + EffectCache mEffectCacheDualTexture; + + bool mSharing; + + std::mutex mutex; +}; + + +_Use_decl_annotations_ +std::shared_ptr EffectFactory::Impl::CreateEffect( + const EffectInfo& info, + const EffectPipelineStateDescription& pipelineState, + const D3D12_INPUT_LAYOUT_DESC& inputLayoutDesc, + int baseDescriptorOffset) +{ + D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {}; + CD3DX12_GPU_DESCRIPTOR_HANDLE textureDescriptorHeapGpuHandle = {}; + CD3DX12_GPU_DESCRIPTOR_HANDLE endDescriptor = {}; + int textureDescriptorHeapIncrement = 0; + + // If we have descriptors, get some information about that + if (mDescriptors != nullptr) + { + descriptorHeapDesc = mDescriptors->GetDesc(); + + // Get the texture offsets and descriptor handles + textureDescriptorHeapIncrement = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + textureDescriptorHeapGpuHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE( + mDescriptors->GetGPUDescriptorHandleForHeapStart(), + baseDescriptorOffset, + textureDescriptorHeapIncrement); + + // For validation, get the last descriptor + endDescriptor = CD3DX12_GPU_DESCRIPTOR_HANDLE( + mDescriptors->GetGPUDescriptorHandleForHeapStart(), + descriptorHeapDesc.NumDescriptors, + textureDescriptorHeapIncrement); + } + + auto checkDescriptor = [endDescriptor] (D3D12_GPU_DESCRIPTOR_HANDLE handle) + { + if (handle.ptr >= endDescriptor.ptr) + { + throw std::exception("Out of descriptor heap space."); + } + }; + + // Modify base pipeline state + EffectPipelineStateDescription derivedPSD = pipelineState; + + // Input layout + derivedPSD.inputLayout = &inputLayoutDesc; + + // Alpha state modification + if ( info.alphaValue < 1.0f ) + { + derivedPSD.depthStencilDesc = &CommonStates::DepthRead; + + if ( info.isPremultipliedAlpha ) + { + derivedPSD.blendDesc = &CommonStates::AlphaBlend; + } + else + { + derivedPSD.blendDesc = &CommonStates::NonPremultiplied; + } + } + + if ( info.enableSkinning ) + { + // SkinnedEffect + if ( mSharing && !info.name.empty() ) + { + auto it = mEffectCacheSkinning.find( info.name ); + if ( mSharing && it != mEffectCacheSkinning.end() ) + { + return it->second; + } + } + + std::shared_ptr effect = std::make_shared( device, EffectFlags::None, derivedPSD ); + + effect->EnableDefaultLighting(); + + effect->SetAlpha( info.alphaValue ); + + // Skinned Effect does not have an ambient material color, or per-vertex color support + + XMVECTOR color = XMLoadFloat3( &info.diffuseColor ); + effect->SetDiffuseColor( color ); + + if ( info.specularColor.x != 0 || info.specularColor.y != 0 || info.specularColor.z != 0 ) + { + color = XMLoadFloat3( &info.specularColor ); + effect->SetSpecularColor( color ); + effect->SetSpecularPower( info.specularPower ); + } + else + { + effect->DisableSpecular(); + } + + if ( info.emissiveColor.x != 0 || info.emissiveColor.y != 0 || info.emissiveColor.z != 0 ) + { + color = XMLoadFloat3( &info.emissiveColor ); + effect->SetEmissiveColor( color ); + } + + if ( mDescriptors != nullptr && info.textureIndex != -1 ) + { + CD3DX12_GPU_DESCRIPTOR_HANDLE handle( + textureDescriptorHeapGpuHandle, + textureDescriptorHeapIncrement * info.textureIndex); + + checkDescriptor(handle); + effect->SetTexture(handle); + } + + if ( mSharing && !info.name.empty() ) + { + std::lock_guard lock(mutex); + mEffectCacheSkinning.insert( EffectCache::value_type( info.name, effect ) ); + } + + return effect; + } + else if ( info.enableDualTexture ) + { + // DualTextureEffect + if ( mSharing && !info.name.empty() ) + { + auto it = mEffectCacheDualTexture.find( info.name ); + if ( mSharing && it != mEffectCacheDualTexture.end() ) + { + return it->second; + } + } + + // set effect flags for creation + int flags = EffectFlags::Lighting; + + if (info.perVertexColor) + { + flags |= EffectFlags::VertexColor; + } + + std::shared_ptr effect = std::make_shared(device, flags, derivedPSD ); + + // Dual texture effect doesn't support lighting (usually it's lightmaps) + effect->SetAlpha( info.alphaValue ); + + XMVECTOR color = XMLoadFloat3( &info.diffuseColor ); + effect->SetDiffuseColor( color ); + + if ( mDescriptors != nullptr && info.textureIndex != -1 ) + { + CD3DX12_GPU_DESCRIPTOR_HANDLE handle( + textureDescriptorHeapGpuHandle, + textureDescriptorHeapIncrement * info.textureIndex); + + checkDescriptor(handle); + effect->SetTexture(handle); + } + + if ( mDescriptors != nullptr && info.textureIndex2 != -1 ) + { + CD3DX12_GPU_DESCRIPTOR_HANDLE handle( + textureDescriptorHeapGpuHandle, + textureDescriptorHeapIncrement * info.textureIndex2); + + checkDescriptor(handle); + effect->SetTexture2(handle); + } + + if ( mSharing && !info.name.empty() ) + { + std::lock_guard lock(mutex); + mEffectCacheDualTexture.insert( EffectCache::value_type( info.name, effect ) ); + } + + return effect; + } + else + { + // BasicEffect + if ( mSharing && !info.name.empty() ) + { + auto it = mEffectCache.find( info.name ); + if ( mSharing && it != mEffectCache.end() ) + { + return it->second; + } + } + + // set effect flags for creation + int flags = EffectFlags::Lighting; + + if (info.perVertexColor) + { + flags |= EffectFlags::VertexColor; + } + + if (info.textureIndex != -1) + { + flags |= EffectFlags::Texture; + } + + std::shared_ptr effect = std::make_shared( device, flags, derivedPSD ); + + effect->EnableDefaultLighting(); + + effect->SetAlpha( info.alphaValue ); + + // Basic Effect does not have an ambient material color + XMVECTOR color = XMLoadFloat3( &info.diffuseColor ); + effect->SetDiffuseColor( color ); + + if ( info.specularColor.x != 0 || info.specularColor.y != 0 || info.specularColor.z != 0 ) + { + color = XMLoadFloat3( &info.specularColor ); + effect->SetSpecularColor( color ); + effect->SetSpecularPower( info.specularPower ); + } + else + { + effect->DisableSpecular(); + } + + if ( info.emissiveColor.x != 0 || info.emissiveColor.y != 0 || info.emissiveColor.z != 0 ) + { + color = XMLoadFloat3( &info.emissiveColor ); + effect->SetEmissiveColor( color ); + } + + if ( mDescriptors != nullptr && info.textureIndex != -1 ) + { + CD3DX12_GPU_DESCRIPTOR_HANDLE handle( + textureDescriptorHeapGpuHandle, + textureDescriptorHeapIncrement * info.textureIndex); + + checkDescriptor(handle); + effect->SetTexture(handle); + } + + if ( mSharing && !info.name.empty() ) + { + std::lock_guard lock(mutex); + mEffectCache.insert( EffectCache::value_type( info.name, effect ) ); + } + + return effect; + } +} + +void EffectFactory::Impl::ReleaseCache() +{ + std::lock_guard lock(mutex); + mEffectCache.clear(); + mEffectCacheSkinning.clear(); + mEffectCacheDualTexture.clear(); +} + + + +//-------------------------------------------------------------------------------------- +// EffectFactory +//-------------------------------------------------------------------------------------- + +EffectFactory::EffectFactory(_In_ ID3D12Device* device) +{ + pImpl = std::make_shared(device, nullptr); +} + +EffectFactory::EffectFactory(_In_ ID3D12DescriptorHeap* descriptors) +{ + if (descriptors == nullptr) + { + throw std::exception("Descriptor heap cannot be null of no device is provided. Use the alternative EffectFactory constructor instead."); + } + + if (descriptors->GetDesc().Type != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + throw std::exception("EffectFactory::CreateEffect requires a CBV_SRV_UAV descriptor heap as input."); + } + + ComPtr device; +#if defined(_XBOX_ONE) && defined(_TITLE) + descriptors->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); +#else + HRESULT hresult = descriptors->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); + if (FAILED(hresult)) + { + throw com_exception(hresult); + } +#endif + + pImpl = std::make_shared(device.Get(), descriptors); +} + +EffectFactory::~EffectFactory() +{ +} + + +EffectFactory::EffectFactory(EffectFactory&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + +EffectFactory& EffectFactory::operator= (EffectFactory&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + +_Use_decl_annotations_ +std::shared_ptr EffectFactory::CreateEffect( + _In_ const EffectInfo& info, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ const D3D12_INPUT_LAYOUT_DESC& inputLayout, + _In_opt_ int descriptorOffset) +{ + return pImpl->CreateEffect(info, pipelineState, inputLayout, descriptorOffset); +} + +void EffectFactory::ReleaseCache() +{ + pImpl->ReleaseCache(); +} + +void EffectFactory::SetSharing( bool enabled ) +{ + pImpl->SetSharing( enabled ); +} diff --git a/Kits/DirectXTK12/Src/EffectTextureFactory.cpp b/Kits/DirectXTK12/Src/EffectTextureFactory.cpp new file mode 100644 index 00000000..9e0d5841 --- /dev/null +++ b/Kits/DirectXTK12/Src/EffectTextureFactory.cpp @@ -0,0 +1,282 @@ +//-------------------------------------------------------------------------------------- +// File: EffectTextureFactory.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Effects.h" +#include "DirectXHelpers.h" +#include "DDSTextureLoader.h" +#include "DescriptorHeap.h" +#include "ResourceUploadBatch.h" +#include "WICTextureLoader.h" +#include "PlatformHelpers.h" + +#include + + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +class EffectTextureFactory::Impl +{ +public: + struct TextureCacheEntry + { + ComPtr mResource; + bool mIsCubeMap; + }; + + typedef std::map< std::wstring, TextureCacheEntry > TextureCache; + + Impl( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ ID3D12DescriptorHeap* descriptorHeap) + : device(device) + , mTextureDescriptorHeap(descriptorHeap) + , mResourceUploadBatch(resourceUploadBatch) + , mSharing(true) + { + *mPath = 0; + } + + Impl( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ size_t numDescriptors, + _In_ D3D12_DESCRIPTOR_HEAP_FLAGS descriptorHeapFlags) + : device(device) + , mTextureDescriptorHeap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, descriptorHeapFlags, numDescriptors) + , mResourceUploadBatch(resourceUploadBatch) + , mSharing(true) + { + *mPath = 0; + } + + void CreateTexture(_In_z_ const wchar_t* name, int descriptorSlot); + + void ReleaseCache(); + void SetSharing( bool enabled ) { mSharing = enabled; } + + wchar_t mPath[MAX_PATH]; + + ::DescriptorHeap mTextureDescriptorHeap; + std::vector mResources; // flat list of unique resources so we can index into it + +private: + ID3D12Device* device; + ResourceUploadBatch& mResourceUploadBatch; + + TextureCache mTextureCache; + bool mSharing; + + std::mutex mutex; +}; + + +_Use_decl_annotations_ +void EffectTextureFactory::Impl::CreateTexture(_In_z_ const wchar_t* name, int descriptorSlot) +{ + if ( !name ) + throw std::exception("invalid arguments"); + + auto it = mTextureCache.find( name ); + + TextureCacheEntry textureEntry = {}; + + if ( mSharing && it != mTextureCache.end() ) + { + textureEntry = it->second; + } + else + { + wchar_t fullName[MAX_PATH] = {}; + wcscpy_s( fullName, mPath ); + wcscat_s( fullName, name ); + + WIN32_FILE_ATTRIBUTE_DATA fileAttr = {}; + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + // Try Current Working Directory (CWD) + wcscpy_s( fullName, name ); + if ( !GetFileAttributesExW(fullName, GetFileExInfoStandard, &fileAttr) ) + { + DebugTrace( "EffectTextureFactory could not find texture file '%ls'\n", name ); + throw std::exception( "CreateTexture" ); + } + } + + wchar_t ext[_MAX_EXT]; + _wsplitpath_s( name, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT ); + + if ( _wcsicmp( ext, L".dds" ) == 0 ) + { + // load resource + HRESULT hr = CreateDDSTextureFromFile( + device, + mResourceUploadBatch, + fullName, + textureEntry.mResource.ReleaseAndGetAddressOf(), + false, + 0u, + nullptr, + &textureEntry.mIsCubeMap); + if ( FAILED(hr) ) + { + DebugTrace( "CreateDDSTextureFromFile failed (%08X) for '%ls'\n", hr, fullName ); + throw std::exception( "CreateDDSTextureFromFile" ); + } + } + else + { + std::lock_guard lock(mutex); + HRESULT hr = CreateWICTextureFromFile( + device, + mResourceUploadBatch, + fullName, + textureEntry.mResource.ReleaseAndGetAddressOf() ); + if ( FAILED(hr) ) + { + DebugTrace( "CreateWICTextureFromFile failed (%08X) for '%ls'\n", hr, fullName ); + throw std::exception( "CreateWICTextureFromFile" ); + } + } + + std::lock_guard lock(mutex); + if (mSharing) + { + mTextureCache.insert( TextureCache::value_type( name, textureEntry ) ); + } + mResources.push_back(textureEntry); + } + + assert(textureEntry.mResource != nullptr); + + // bind a new descriptor in slot + auto textureDescriptor = mTextureDescriptorHeap.GetCpuHandle(descriptorSlot); + DirectX::CreateShaderResourceView(device, textureEntry.mResource.Get(), textureDescriptor, textureEntry.mIsCubeMap); +} + +void EffectTextureFactory::Impl::ReleaseCache() +{ + std::lock_guard lock(mutex); + mTextureCache.clear(); +} + + + +//-------------------------------------------------------------------------------------- +// EffectTextureFactory +//-------------------------------------------------------------------------------------- + +EffectTextureFactory::EffectTextureFactory( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ ID3D12DescriptorHeap* descriptorHeap) +{ + pImpl = std::make_unique(device, resourceUploadBatch, descriptorHeap); +} + +EffectTextureFactory::EffectTextureFactory( + _In_ ID3D12Device* device, + _Inout_ ResourceUploadBatch& resourceUploadBatch, + _In_ size_t numDescriptors, + _In_ D3D12_DESCRIPTOR_HEAP_FLAGS descriptorHeapFlags) +{ + pImpl = std::make_unique(device, resourceUploadBatch, numDescriptors, descriptorHeapFlags); +} + +EffectTextureFactory::~EffectTextureFactory() +{ +} + + +EffectTextureFactory::EffectTextureFactory(EffectTextureFactory&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + +EffectTextureFactory& EffectTextureFactory::operator= (EffectTextureFactory&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + +_Use_decl_annotations_ +void EffectTextureFactory::CreateTexture(_In_z_ const wchar_t* name, int descriptorIndex) +{ + pImpl->CreateTexture(name, descriptorIndex); +} + +void EffectTextureFactory::ReleaseCache() +{ + pImpl->ReleaseCache(); +} + +void EffectTextureFactory::SetSharing( bool enabled ) +{ + pImpl->SetSharing( enabled ); +} + +void EffectTextureFactory::SetDirectory( _In_opt_z_ const wchar_t* path ) +{ + if ( path && *path != 0 ) + { + wcscpy_s( pImpl->mPath, path ); + size_t len = wcsnlen( pImpl->mPath, MAX_PATH ); + if ( len > 0 && len < (MAX_PATH-1) ) + { + // Ensure it has a trailing slash + if ( pImpl->mPath[len-1] != L'\\' ) + { + pImpl->mPath[len] = L'\\'; + pImpl->mPath[len+1] = 0; + } + } + } + else + *pImpl->mPath = 0; +} + +ID3D12DescriptorHeap* EffectTextureFactory::DescriptorHeap() const +{ + return pImpl->mTextureDescriptorHeap.Heap(); +} + +// Shorthand accessors for the descriptor heap +D3D12_CPU_DESCRIPTOR_HANDLE EffectTextureFactory::GetCpuDescriptorHandle(size_t index) const +{ + return pImpl->mTextureDescriptorHeap.GetCpuHandle(index); +} + +D3D12_GPU_DESCRIPTOR_HANDLE EffectTextureFactory::GetGpuDescriptorHandle(size_t index) const +{ + return pImpl->mTextureDescriptorHeap.GetGpuHandle(index); +} + +size_t EffectTextureFactory::ResourceCount() const +{ + return pImpl->mResources.size(); +} + +_Use_decl_annotations_ +void EffectTextureFactory::GetResource(size_t slot, ID3D12Resource** resource, bool* isCubeMap) +{ + if (slot >= pImpl->mResources.size()) + throw std::exception("Accessing resource out of range."); + + const auto& textureEntry = pImpl->mResources[slot]; + + textureEntry.mResource.CopyTo(resource); + *isCubeMap = textureEntry.mIsCubeMap; +} diff --git a/Kits/DirectXTK12/Src/EnvironmentMapEffect.cpp b/Kits/DirectXTK12/Src/EnvironmentMapEffect.cpp new file mode 100644 index 00000000..0ffd6cb8 --- /dev/null +++ b/Kits/DirectXTK12/Src/EnvironmentMapEffect.cpp @@ -0,0 +1,498 @@ +//-------------------------------------------------------------------------------------- +// File: EnvironmentMapEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +// Constant buffer layout. Must match the shader! +struct EnvironmentMapEffectConstants +{ + XMVECTOR environmentMapSpecular; + float environmentMapAmount; + float fresnelFactor; + float pad[2]; + + XMVECTOR diffuseColor; + XMVECTOR emissiveColor; + + XMVECTOR lightDirection[IEffectLights::MaxDirectionalLights]; + XMVECTOR lightDiffuseColor[IEffectLights::MaxDirectionalLights]; + + XMVECTOR eyePosition; + + XMVECTOR fogColor; + XMVECTOR fogVector; + + XMMATRIX world; + XMVECTOR worldInverseTranspose[3]; + XMMATRIX worldViewProj; +}; + +static_assert( ( sizeof(EnvironmentMapEffectConstants) % 16 ) == 0, "CB size not padded correctly" ); + + +// Traits type describes our characteristics to the EffectBase template. +struct EnvironmentMapEffectTraits +{ + typedef EnvironmentMapEffectConstants ConstantBufferType; + + static const int VertexShaderCount = 4; + static const int PixelShaderCount = 4; + static const int ShaderPermutationCount = 16; +}; + + +// Internal EnvironmentMapEffect implementation class. +class EnvironmentMapEffect::Impl : public EffectBase +{ +public: + Impl(_In_ ID3D12Device* device, + int effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + bool fresnelEnabled, + bool specularEnabled); + + enum RootParameterIndex + { + TextureSRV, + CubemapSRV, + ConstantBuffer, + RootParameterCount + }; + + EffectLights lights; + + D3D12_GPU_DESCRIPTOR_HANDLE texture; + D3D12_GPU_DESCRIPTOR_HANDLE environmentMap; + + int GetCurrentShaderPermutation(bool fresnelEnabled, bool specularEnabled) const; + + void Apply(_In_ ID3D12GraphicsCommandList* commandList); +}; + + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_VSEnvMap.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_VSEnvMapFresnel.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_VSEnvMapOneLight.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_VSEnvMapOneLightFresnel.inc" + + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_PSEnvMap.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_PSEnvMapNoFog.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_PSEnvMapSpecular.inc" + #include "Shaders/Compiled/XboxOneEnvironmentMapEffect_PSEnvMapSpecularNoFog.inc" +#else + #include "Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc" + + #include "Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc" + #include "Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc" +#endif +} + + +const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = +{ + { EnvironmentMapEffect_VSEnvMap, sizeof(EnvironmentMapEffect_VSEnvMap) }, + { EnvironmentMapEffect_VSEnvMapFresnel, sizeof(EnvironmentMapEffect_VSEnvMapFresnel) }, + { EnvironmentMapEffect_VSEnvMapOneLight, sizeof(EnvironmentMapEffect_VSEnvMapOneLight) }, + { EnvironmentMapEffect_VSEnvMapOneLightFresnel, sizeof(EnvironmentMapEffect_VSEnvMapOneLightFresnel) }, +}; + + +const int EffectBase::VertexShaderIndices[] = +{ + 0, // basic + 0, // basic, no fog + 1, // fresnel + 1, // fresnel, no fog + 0, // specular + 0, // specular, no fog + 1, // fresnel + specular + 1, // fresnel + specular, no fog + + 2, // one light + 2, // one light, no fog + 3, // one light, fresnel + 3, // one light, fresnel, no fog + 2, // one light, specular + 2, // one light, specular, no fog + 3, // one light, fresnel + specular + 3, // one light, fresnel + specular, no fog + +}; + + +const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = +{ + { EnvironmentMapEffect_PSEnvMap, sizeof(EnvironmentMapEffect_PSEnvMap) }, + { EnvironmentMapEffect_PSEnvMapNoFog, sizeof(EnvironmentMapEffect_PSEnvMapNoFog) }, + { EnvironmentMapEffect_PSEnvMapSpecular, sizeof(EnvironmentMapEffect_PSEnvMapSpecular) }, + { EnvironmentMapEffect_PSEnvMapSpecularNoFog, sizeof(EnvironmentMapEffect_PSEnvMapSpecularNoFog) }, +}; + + +const int EffectBase::PixelShaderIndices[] = +{ + 0, // basic + 1, // basic, no fog + 0, // fresnel + 1, // fresnel, no fog + 2, // specular + 3, // specular, no fog + 2, // fresnel + specular + 3, // fresnel + specular, no fog + + 0, // one light + 1, // one light, no fog + 0, // one light, fresnel + 1, // one light, fresnel, no fog + 2, // one light, specular + 3, // one light, specular, no fog + 2, // one light, fresnel + specular + 3, // one light, fresnel + specular, no fog +}; + + +// Global pool of per-device EnvironmentMapEffect resources. +SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; + + +// Constructor. +EnvironmentMapEffect::Impl::Impl( + _In_ ID3D12Device* device, + int effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + bool fresnelEnabled, + bool specularEnabled) + : EffectBase(device) +{ + static_assert( _countof(EffectBase::VertexShaderIndices) == EnvironmentMapEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::VertexShaderBytecode) == EnvironmentMapEffectTraits::VertexShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderBytecode) == EnvironmentMapEffectTraits::PixelShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderIndices) == EnvironmentMapEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + + // Create root signature + { + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC samplers[2]; + samplers[0] = CD3DX12_STATIC_SAMPLER_DESC(0); + samplers[1] = CD3DX12_STATIC_SAMPLER_DESC(1); + + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + + // Texture 1 + CD3DX12_DESCRIPTOR_RANGE descriptorRange1; + descriptorRange1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable(1, &descriptorRange1); + + // Texture 2 + CD3DX12_DESCRIPTOR_RANGE descriptorRange2; + descriptorRange2.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1); + rootParameters[RootParameterIndex::CubemapSRV].InitAsDescriptorTable(1, &descriptorRange2); + + // Create the root signature + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, _countof(samplers), samplers, rootSignatureFlags); + + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, mRootSignature.ReleaseAndGetAddressOf())); + } + + fog.enabled = (effectFlags & EffectFlags::Fog) != 0; + + constants.environmentMapAmount = 1; + constants.fresnelFactor = 1; + + XMVECTOR unwantedOutput[MaxDirectionalLights]; + + lights.InitializeConstants(unwantedOutput[0], constants.lightDirection, constants.lightDiffuseColor, unwantedOutput); + + { // Create pipeline state + int sp = GetCurrentShaderPermutation(fresnelEnabled, specularEnabled); + int vi = EffectBase::VertexShaderIndices[sp]; + int pi = EffectBase::PixelShaderIndices[sp]; + + EffectBase::CreatePipelineState( + mRootSignature.Get(), + pipelineDescription.inputLayout, + &EffectBase::VertexShaderBytecode[vi], + &EffectBase::PixelShaderBytecode[pi], + pipelineDescription.blendDesc, + pipelineDescription.depthStencilDesc, + pipelineDescription.rasterizerDesc, + pipelineDescription.renderTargetState, + pipelineDescription.primitiveTopology, + pipelineDescription.stripCutValue); + } +} + + +int EnvironmentMapEffect::Impl::GetCurrentShaderPermutation(bool fresnelEnabled, bool specularEnabled) const +{ + int permutation = 0; + + // Use optimized shaders if fog is disabled. + if (!fog.enabled) + { + permutation += 1; + } + + // Support fresnel or specular? + if (fresnelEnabled) + { + permutation += 2; + } + + if (specularEnabled) + { + permutation += 4; + } + + // Use the only-bother-with-the-first-light shader optimization? + if (!lights.lightEnabled[1] && !lights.lightEnabled[2]) + { + permutation += 8; + } + + return permutation; +} + + +// Sets our state onto the D3D device. +void EnvironmentMapEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + // Compute derived parameter values. + matrices.SetConstants(dirtyFlags, constants.worldViewProj); + + fog.SetConstants(dirtyFlags, matrices.worldView, constants.fogVector); + + lights.SetConstants(dirtyFlags, matrices, constants.world, constants.worldInverseTranspose, constants.eyePosition, constants.diffuseColor, constants.emissiveColor, true); + + UpdateConstants(); + + // Set the resources and state + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::CubemapSRV, environmentMap); + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, GetConstantBufferGpuAddress()); + commandList->SetPipelineState(EffectBase::mPipelineState.Get()); +} + + +// Public constructor. +EnvironmentMapEffect::EnvironmentMapEffect( + _In_ ID3D12Device* device, + int effectFlags, + const EffectPipelineStateDescription& pipelineDescription, + bool fresnelEnabled, + bool specularEnabled) + : pImpl(new Impl(device, effectFlags, pipelineDescription, fresnelEnabled, specularEnabled)) +{ +} + + +// Move constructor. +EnvironmentMapEffect::EnvironmentMapEffect(EnvironmentMapEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +EnvironmentMapEffect& EnvironmentMapEffect::operator= (EnvironmentMapEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +EnvironmentMapEffect::~EnvironmentMapEffect() +{ +} + + +void EnvironmentMapEffect::Apply( + _In_ ID3D12GraphicsCommandList* cmdList) +{ + pImpl->Apply(cmdList); +} + + +void XM_CALLCONV EnvironmentMapEffect::SetWorld(FXMMATRIX value) +{ + pImpl->matrices.world = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetView(FXMMATRIX value) +{ + pImpl->matrices.view = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetProjection(FXMMATRIX value) +{ + pImpl->matrices.projection = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetDiffuseColor(FXMVECTOR value) +{ + pImpl->lights.diffuseColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetEmissiveColor(FXMVECTOR value) +{ + pImpl->lights.emissiveColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void EnvironmentMapEffect::SetAlpha(float value) +{ + pImpl->lights.alpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetAmbientLightColor(FXMVECTOR value) +{ + pImpl->lights.ambientLightColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void EnvironmentMapEffect::SetLightEnabled(int whichLight, bool value) +{ + XMVECTOR unwantedOutput[MaxDirectionalLights] = {}; + + pImpl->dirtyFlags |= pImpl->lights.SetLightEnabled(whichLight, value, pImpl->constants.lightDiffuseColor, unwantedOutput); +} + + +void XM_CALLCONV EnvironmentMapEffect::SetLightDirection(int whichLight, FXMVECTOR value) +{ + EffectLights::ValidateLightIndex(whichLight); + + pImpl->constants.lightDirection[whichLight] = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetLightDiffuseColor(int whichLight, FXMVECTOR value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightDiffuseColor(whichLight, value, pImpl->constants.lightDiffuseColor); +} + + +void XM_CALLCONV EnvironmentMapEffect::SetLightSpecularColor(int, FXMVECTOR) +{ + // Unsupported interface method. +} + + +void EnvironmentMapEffect::EnableDefaultLighting() +{ + EffectLights::EnableDefaultLighting(this); +} + + +void EnvironmentMapEffect::SetFogStart(float value) +{ + pImpl->fog.start = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void EnvironmentMapEffect::SetFogEnd(float value) +{ + pImpl->fog.end = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetFogColor(FXMVECTOR value) +{ + pImpl->constants.fogColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void EnvironmentMapEffect::SetTexture(_In_opt_ D3D12_GPU_DESCRIPTOR_HANDLE value) +{ + pImpl->texture = value; +} + + +void EnvironmentMapEffect::SetEnvironmentMap(_In_opt_ D3D12_GPU_DESCRIPTOR_HANDLE value) +{ + pImpl->environmentMap = value; +} + + +void EnvironmentMapEffect::SetEnvironmentMapAmount(float value) +{ + pImpl->constants.environmentMapAmount = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void XM_CALLCONV EnvironmentMapEffect::SetEnvironmentMapSpecular(FXMVECTOR value) +{ + pImpl->constants.environmentMapSpecular = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void EnvironmentMapEffect::SetFresnelFactor(float value) +{ + pImpl->constants.fresnelFactor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} diff --git a/Kits/DirectXTK12/Src/GamePad.cpp b/Kits/DirectXTK12/Src/GamePad.cpp new file mode 100644 index 00000000..5475f1d2 --- /dev/null +++ b/Kits/DirectXTK12/Src/GamePad.cpp @@ -0,0 +1,1239 @@ +//-------------------------------------------------------------------------------------- +// File: GamePad.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "GamePad.h" +#include "PlatformHelpers.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +namespace +{ + float ApplyLinearDeadZone( float value, float maxValue, float deadZoneSize ) + { + if ( value < -deadZoneSize ) + { + // Increase negative values to remove the deadzone discontinuity. + value += deadZoneSize; + } + else if ( value > deadZoneSize ) + { + // Decrease positive values to remove the deadzone discontinuity. + value -= deadZoneSize; + } + else + { + // Values inside the deadzone come out zero. + return 0; + } + + // Scale into 0-1 range. + float scaledValue = value / (maxValue - deadZoneSize); + return std::max( -1.f, std::min( scaledValue, 1.f ) ); + } + + void ApplyStickDeadZone( float x, float y, GamePad::DeadZone deadZoneMode, float maxValue, float deadZoneSize, + _Out_ float& resultX, _Out_ float& resultY) + { + switch( deadZoneMode ) + { + case GamePad::DEAD_ZONE_INDEPENDENT_AXES: + resultX = ApplyLinearDeadZone( x, maxValue, deadZoneSize ); + resultY = ApplyLinearDeadZone( y, maxValue, deadZoneSize ); + break; + + case GamePad::DEAD_ZONE_CIRCULAR: + { + float dist = sqrtf( x*x + y*y ); + float wanted = ApplyLinearDeadZone( dist, maxValue, deadZoneSize ); + + float scale = (wanted > 0.f) ? ( wanted / dist ) : 0.f; + + resultX = std::max( -1.f, std::min( x * scale, 1.f ) ); + resultY = std::max( -1.f, std::min( y * scale, 1.f ) ); + } + break; + + default: // GamePad::DEAD_ZONE_NONE + resultX = ApplyLinearDeadZone( x, maxValue, 0 ); + resultY = ApplyLinearDeadZone( y, maxValue, 0 ); + break; + } + } +} + + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +//====================================================================================== +// Windows::Gaming::Input (Windows 10) +//====================================================================================== + +#include + +class GamePad::Impl +{ +public: + Impl(GamePad* owner) : + mOwner(owner) + { + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::Foundation; + + mAddedToken.value = 0; + mRemovedToken.value = 0; + + if ( s_gamePad ) + { + throw std::exception( "GamePad is a singleton" ); + } + + s_gamePad = this; + + mChanged.reset( CreateEventEx( nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !mChanged ) + { + throw std::exception( "CreateEventEx" ); + } + + HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_Gaming_Input_Gamepad).Get(), mStatics.GetAddressOf() ); + ThrowIfFailed( hr ); + + typedef __FIEventHandler_1_Windows__CGaming__CInput__CGamepad AddedHandler; + hr = mStatics->add_GamepadAdded(Callback(GamepadAdded).Get(), &mAddedToken ); + ThrowIfFailed( hr ); + + typedef __FIEventHandler_1_Windows__CGaming__CInput__CGamepad RemovedHandler; + hr = mStatics->add_GamepadRemoved(Callback(GamepadRemoved).Get(), &mRemovedToken ); + ThrowIfFailed( hr ); + + ScanGamePads(); + } + + ~Impl() + { + if ( mStatics ) + { + mStatics->remove_GamepadAdded( mAddedToken ); + mStatics->remove_GamepadRemoved( mRemovedToken ); + + mStatics.Reset(); + } + + s_gamePad = nullptr; + } + + void GetState( int player, _Out_ State& state, DeadZone deadZoneMode ) + { + using namespace Microsoft::WRL; + using namespace ABI::Windows::Gaming::Input; + + if ( WaitForSingleObjectEx( mChanged.get(), 0, FALSE ) == WAIT_OBJECT_0 ) + { + ScanGamePads(); + } + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + GamepadReading reading; + HRESULT hr = mGamePad[ player ]->GetCurrentReading( &reading ); + if ( SUCCEEDED(hr) ) + { + state.connected = true; + state.packet = reading.Timestamp; + + state.buttons.a = (reading.Buttons & GamepadButtons::GamepadButtons_A) != 0; + state.buttons.b = (reading.Buttons & GamepadButtons::GamepadButtons_B) != 0; + state.buttons.x = (reading.Buttons & GamepadButtons::GamepadButtons_X) != 0; + state.buttons.y = (reading.Buttons & GamepadButtons::GamepadButtons_Y) != 0; + + state.buttons.leftStick = (reading.Buttons & GamepadButtons::GamepadButtons_LeftThumbstick) != 0; + state.buttons.rightStick = (reading.Buttons & GamepadButtons::GamepadButtons_RightThumbstick) != 0; + + state.buttons.leftShoulder = (reading.Buttons & GamepadButtons::GamepadButtons_LeftShoulder) != 0; + state.buttons.rightShoulder = (reading.Buttons & GamepadButtons::GamepadButtons_RightShoulder) != 0; + + state.buttons.back = (reading.Buttons & GamepadButtons::GamepadButtons_View) != 0; + state.buttons.start = (reading.Buttons & GamepadButtons::GamepadButtons_Menu) != 0; + + state.dpad.up = (reading.Buttons & GamepadButtons::GamepadButtons_DPadUp) != 0; + state.dpad.down = (reading.Buttons & GamepadButtons::GamepadButtons_DPadDown) != 0; + state.dpad.right = (reading.Buttons & GamepadButtons::GamepadButtons_DPadRight) != 0; + state.dpad.left = (reading.Buttons & GamepadButtons::GamepadButtons_DPadLeft) != 0; + + ApplyStickDeadZone( static_cast(reading.LeftThumbstickX), static_cast(reading.LeftThumbstickY), + deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, + static_cast(state.thumbSticks.leftX), static_cast(state.thumbSticks.leftY) ); + + ApplyStickDeadZone( static_cast(reading.RightThumbstickX), static_cast(reading.RightThumbstickY), + deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, + static_cast(state.thumbSticks.rightX), static_cast(state.thumbSticks.rightY) ); + + state.triggers.left = static_cast(reading.LeftTrigger); + state.triggers.right = static_cast(reading.RightTrigger); + + return; + } + } + } + + memset( &state, 0, sizeof(State) ); + } + + void GetCapabilities( int player, _Out_ Capabilities& caps ) + { + if ( WaitForSingleObjectEx( mChanged.get(), 0, FALSE ) == WAIT_OBJECT_0 ) + { + ScanGamePads(); + } + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + caps.connected = true; + caps.gamepadType = Capabilities::GAMEPAD; + caps.id = 0; + return; + } + } + + memset( &caps, 0, sizeof(Capabilities) ); + } + + bool SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) + { + using namespace ABI::Windows::Gaming::Input; + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + GamepadVibration vib; + vib.LeftMotor = leftMotor; + vib.RightMotor = rightMotor; + vib.LeftTrigger = leftTrigger; + vib.RightTrigger = rightTrigger; + HRESULT hr = mGamePad[ player ]->put_Vibration(vib); + + if ( SUCCEEDED(hr) ) + return true; + } + } + + return false; + } + + void Suspend() + { + for( size_t j = 0; j < MAX_PLAYER_COUNT; ++j ) + { + mGamePad[ j ].Reset(); + } + } + + void Resume() + { + // Make sure we rescan gamepads + SetEvent( mChanged.get() ); + } + + GamePad* mOwner; + + static GamePad::Impl* s_gamePad; + +private: + void ScanGamePads() + { + using namespace ABI::Windows::Foundation::Collections; + using namespace ABI::Windows::Gaming::Input; + + ComPtr> pads; + HRESULT hr = mStatics->get_Gamepads( pads.GetAddressOf() ); + ThrowIfFailed( hr ); + + unsigned int count = 0; + hr = pads->get_Size( &count ); + ThrowIfFailed( hr ); + + // Check for removed gamepads + for( size_t j = 0; j < MAX_PLAYER_COUNT; ++j ) + { + if ( mGamePad[ j ] ) + { + unsigned int k = 0; + for( ; k < count; ++k ) + { + ComPtr pad; + hr = pads->GetAt( k, pad.GetAddressOf() ); + if ( SUCCEEDED(hr) && ( pad == mGamePad[ j ] ) ) + { + break; + } + } + + if ( k >= count ) + { + mGamePad[ j ].Reset(); + } + } + } + + // Check for added gamepads + for( unsigned int j = 0; j < count; ++j ) + { + ComPtr pad; + hr = pads->GetAt( j, pad.GetAddressOf() ); + if ( SUCCEEDED(hr) ) + { + size_t empty = MAX_PLAYER_COUNT; + size_t k = 0; + for( ; k < MAX_PLAYER_COUNT; ++k ) + { + if ( mGamePad[ k ] == pad ) + { + break; + } + else if ( !mGamePad[ k ] ) + { + if ( empty >= MAX_PLAYER_COUNT ) + empty = k; + } + } + + if ( k >= MAX_PLAYER_COUNT ) + { + // Silently ignore "extra" gamepads as there's no hard limit + if ( empty < MAX_PLAYER_COUNT ) + { + mGamePad[ empty ] = pad; + } + } + } + } + } + + ComPtr mStatics; + ComPtr mGamePad[ MAX_PLAYER_COUNT ]; + + EventRegistrationToken mAddedToken; + EventRegistrationToken mRemovedToken; + + ScopedHandle mChanged; + + static HRESULT GamepadAdded( IInspectable *, ABI::Windows::Gaming::Input::IGamepad* ) + { + if ( s_gamePad ) + { + SetEvent( s_gamePad->mChanged.get() ); + } + return S_OK; + } + + static HRESULT GamepadRemoved( IInspectable *, ABI::Windows::Gaming::Input::IGamepad* ) + { + if ( s_gamePad ) + { + SetEvent( s_gamePad->mChanged.get() ); + } + return S_OK; + } +}; + +GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; + +#elif defined(_XBOX_ONE) + +//====================================================================================== +// Windows::Xbox::Input (Xbox One) +//====================================================================================== + +#include + +#ifdef _TITLE +#include + +namespace +{ + +class GamepadAddedListener : public Microsoft::WRL::RuntimeClass, + ABI::Windows::Foundation::IEventHandler, + Microsoft::WRL::FtmBase> +{ +public: + GamepadAddedListener(HANDLE event) : mEvent(event) {} + + STDMETHOD(Invoke)(_In_ IInspectable *, _In_ ABI::Windows::Xbox::Input::IGamepadAddedEventArgs * ) override + { + SetEvent( mEvent ); + return S_OK; + } + +private: + HANDLE mEvent; +}; + +class GamepadRemovedListener : public Microsoft::WRL::RuntimeClass, + ABI::Windows::Foundation::IEventHandler, + Microsoft::WRL::FtmBase> +{ +public: + GamepadRemovedListener(HANDLE event) : mEvent(event) {} + + STDMETHOD(Invoke)(_In_ IInspectable *, _In_ ABI::Windows::Xbox::Input::IGamepadRemovedEventArgs * ) override + { + SetEvent( mEvent ); + return S_OK; + } + +private: + HANDLE mEvent; +}; + +} +#endif + +class GamePad::Impl +{ +public: + Impl(GamePad *owner) : + mOwner(owner) + { + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::Foundation; + + mAddedToken.value = 0; + mRemovedToken.value = 0; + + if ( s_gamePad ) + { + throw std::exception( "GamePad is a singleton" ); + } + + s_gamePad = this; + + mChanged.reset( CreateEventEx( nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE ) ); + if ( !mChanged ) + { + throw std::exception( "CreateEventEx" ); + } + + HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_Xbox_Input_Gamepad).Get(), mStatics.GetAddressOf() ); + ThrowIfFailed( hr ); + +#ifdef _TITLE + // This is a workaround for some registration issues in the GameOS + + hr = mStatics->add_GamepadAdded(Make(mChanged.get()).Get(), &mAddedToken ); + ThrowIfFailed( hr ); + + hr = mStatics->add_GamepadRemoved(Make(mChanged.get()).Get(), &mRemovedToken ); + ThrowIfFailed( hr ); +#else + typedef __FIEventHandler_1_Windows__CXbox__CInput__CGamepadAddedEventArgs AddedHandler; + hr = mStatics->add_GamepadAdded(Callback(GamepadAdded).Get(), &mAddedToken ); + ThrowIfFailed( hr ); + + typedef __FIEventHandler_1_Windows__CXbox__CInput__CGamepadRemovedEventArgs RemovedHandler; + hr = mStatics->add_GamepadRemoved(Callback(GamepadRemoved).Get(), &mRemovedToken ); + ThrowIfFailed( hr ); +#endif + + ScanGamePads(); + } + + ~Impl() + { + if ( mStatics ) + { + mStatics->remove_GamepadAdded( mAddedToken ); + mStatics->remove_GamepadRemoved( mRemovedToken ); + + mStatics.Reset(); + } + + s_gamePad = nullptr; + } + + void GetState( int player, _Out_ State& state, DeadZone deadZoneMode ) + { + using namespace Microsoft::WRL; + using namespace ABI::Windows::Xbox::Input; + + if ( WaitForSingleObjectEx( mChanged.get(), 0, FALSE ) == WAIT_OBJECT_0 ) + { + ScanGamePads(); + } + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + RawGamepadReading reading; + HRESULT hr = mGamePad[ player ]->GetRawCurrentReading( &reading ); + if ( SUCCEEDED(hr) ) + { + state.connected = true; + state.packet = reading.Timestamp; + + state.buttons.a = (reading.Buttons & GamepadButtons::GamepadButtons_A) != 0; + state.buttons.b = (reading.Buttons & GamepadButtons::GamepadButtons_B) != 0; + state.buttons.x = (reading.Buttons & GamepadButtons::GamepadButtons_X) != 0; + state.buttons.y = (reading.Buttons & GamepadButtons::GamepadButtons_Y) != 0; + + state.buttons.leftStick = (reading.Buttons & GamepadButtons::GamepadButtons_LeftThumbstick) != 0; + state.buttons.rightStick = (reading.Buttons & GamepadButtons::GamepadButtons_RightThumbstick) != 0; + + state.buttons.leftShoulder = (reading.Buttons & GamepadButtons::GamepadButtons_LeftShoulder) != 0; + state.buttons.rightShoulder = (reading.Buttons & GamepadButtons::GamepadButtons_RightShoulder) != 0; + + state.buttons.back = (reading.Buttons & GamepadButtons::GamepadButtons_View) != 0; + state.buttons.start = (reading.Buttons & GamepadButtons::GamepadButtons_Menu) != 0; + + state.dpad.up = (reading.Buttons & GamepadButtons::GamepadButtons_DPadUp) != 0; + state.dpad.down = (reading.Buttons & GamepadButtons::GamepadButtons_DPadDown) != 0; + state.dpad.right = (reading.Buttons & GamepadButtons::GamepadButtons_DPadRight) != 0; + state.dpad.left = (reading.Buttons & GamepadButtons::GamepadButtons_DPadLeft) != 0; + + ApplyStickDeadZone( reading.LeftThumbstickX, reading.LeftThumbstickY, + deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, + state.thumbSticks.leftX, state.thumbSticks.leftY ); + + ApplyStickDeadZone( reading.RightThumbstickX, reading.RightThumbstickY, + deadZoneMode, 1.f, .24f /* Recommended Xbox One deadzone */, + state.thumbSticks.rightX, state.thumbSticks.rightY ); + + state.triggers.left = reading.LeftTrigger; + state.triggers.right = reading.RightTrigger; + + return; + } + } + } + + memset( &state, 0, sizeof(State) ); + } + + void GetCapabilities( int player, _Out_ Capabilities& caps ) + { + using namespace ABI::Windows::Xbox::Input; + + if ( WaitForSingleObjectEx( mChanged.get(), 0, FALSE ) == WAIT_OBJECT_0 ) + { + ScanGamePads(); + } + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + caps.connected = true; + caps.gamepadType = Capabilities::GAMEPAD; + + ComPtr ctrl; + HRESULT hr = mGamePad[ player ].As( &ctrl ); + if ( SUCCEEDED(hr) && ctrl ) + { + hr = ctrl->get_Id( &caps.id ); + if ( FAILED(hr) ) + caps.id = 0; + } + else + caps.id = 0; + + return; + } + } + + memset( &caps, 0, sizeof(Capabilities) ); + } + + bool SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) + { + using namespace ABI::Windows::Xbox::Input; + + if ( ( player >= 0 ) && ( player < MAX_PLAYER_COUNT ) ) + { + if ( mGamePad[ player ] ) + { + HRESULT hr; + try + { + GamepadVibration vib; + vib.LeftMotorLevel = leftMotor; + vib.RightMotorLevel = rightMotor; + vib.LeftTriggerLevel = leftTrigger; + vib.RightTriggerLevel = rightTrigger; + hr = mGamePad[ player ]->SetVibration(vib); + } + catch( ... ) + { + // Handle case where gamepad might be invalid + hr = E_FAIL; + } + + if ( SUCCEEDED(hr) ) + return true; + } + } + + return false; + } + + void Suspend() + { + for( size_t j = 0; j < MAX_PLAYER_COUNT; ++j ) + { + mGamePad[ j ].Reset(); + } + } + + void Resume() + { + // Make sure we rescan gamepads + SetEvent( mChanged.get() ); + } + + GamePad* mOwner; + + static GamePad::Impl* s_gamePad; + +private: + void ScanGamePads() + { + using namespace ABI::Windows::Foundation::Collections; + using namespace ABI::Windows::Xbox::Input; + + ComPtr> pads; + HRESULT hr = mStatics->get_Gamepads( pads.GetAddressOf() ); + ThrowIfFailed( hr ); + + unsigned int count = 0; + hr = pads->get_Size( &count ); + ThrowIfFailed( hr ); + + // Check for removed gamepads + for( size_t j = 0; j < MAX_PLAYER_COUNT; ++j ) + { + if ( mGamePad[ j ] ) + { + unsigned int k = 0; + for( ; k < count; ++k ) + { + ComPtr pad; + hr = pads->GetAt( k, pad.GetAddressOf() ); + if ( SUCCEEDED(hr) && ( pad == mGamePad[ j ] ) ) + { + break; + } + } + + if ( k >= count ) + { + mGamePad[ j ].Reset(); + } + } + } + + // Check for added gamepads + for( unsigned int j = 0; j < count; ++j ) + { + ComPtr pad; + hr = pads->GetAt( j, pad.GetAddressOf() ); + if ( SUCCEEDED(hr) ) + { + size_t empty = MAX_PLAYER_COUNT; + size_t k = 0; + for( ; k < MAX_PLAYER_COUNT; ++k ) + { + if ( mGamePad[ k ] == pad ) + { + break; + } + else if ( !mGamePad[ k ] ) + { + if ( empty >= MAX_PLAYER_COUNT ) + empty = k; + } + } + + if ( k >= MAX_PLAYER_COUNT ) + { + if ( empty >= MAX_PLAYER_COUNT ) + { + throw std::exception( "Too many gamepads found" ); + } + + mGamePad[ empty ] = pad; + } + } + } + } + + ComPtr mStatics; + ComPtr mGamePad[ MAX_PLAYER_COUNT ]; + + EventRegistrationToken mAddedToken; + EventRegistrationToken mRemovedToken; + + ScopedHandle mChanged; + +#ifndef _TITLE + static HRESULT GamepadAdded( IInspectable *, ABI::Windows::Xbox::Input::IGamepadAddedEventArgs * ) + { + if ( s_gamePad ) + { + SetEvent( s_gamePad->mChanged.get() ); + } + return S_OK; + } + + static HRESULT GamepadRemoved( IInspectable *, ABI::Windows::Xbox::Input::IGamepadRemovedEventArgs* ) + { + if ( s_gamePad ) + { + SetEvent( s_gamePad->mChanged.get() ); + } + return S_OK; + } +#endif +}; + +GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; + + +#elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + +//====================================================================================== +// Null device for Windows Phone +//====================================================================================== + +class GamePad::Impl +{ +public: + Impl(GamePad* owner) : + mOwner(owner) + { + if ( s_gamePad ) + { + throw std::exception( "GamePad is a singleton" ); + } + + s_gamePad = this; + } + + ~Impl() + { + s_gamePad = nullptr; + } + + void GetState(int player, _Out_ State& state, DeadZone) + { + UNREFERENCED_PARAMETER(player); + + memset( &state, 0, sizeof(State) ); + } + + void GetCapabilities(int player, _Out_ Capabilities& caps) + { + UNREFERENCED_PARAMETER(player); + + memset( &caps, 0, sizeof(Capabilities) ); + } + + bool SetVibration(int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger) + { + UNREFERENCED_PARAMETER(player); + UNREFERENCED_PARAMETER(leftMotor); + UNREFERENCED_PARAMETER(rightMotor); + UNREFERENCED_PARAMETER(leftTrigger); + UNREFERENCED_PARAMETER(rightTrigger); + + return false; + } + + void Suspend() + { + } + + void Resume() + { + } + + GamePad* mOwner; + + static GamePad::Impl* s_gamePad; +}; + +GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; + + +#else + +//====================================================================================== +// XInput +//====================================================================================== + +#include + +static_assert( GamePad::MAX_PLAYER_COUNT == XUSER_MAX_COUNT, "xinput.h mismatch" ); + +class GamePad::Impl +{ +public: + Impl(GamePad* owner) : + mOwner(owner) + { + for( int j = 0; j < XUSER_MAX_COUNT; ++j ) + { + ClearSlot( j, 0 ); + } + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + mSuspended = false; +#endif + + if ( s_gamePad ) + { + throw std::exception( "GamePad is a singleton" ); + } + + s_gamePad = this; + } + + ~Impl() + { + s_gamePad = nullptr; + } + + void GetState( int player, _Out_ State& state, DeadZone deadZoneMode ) + { + if ( !ThrottleRetry(player) ) + { +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + if ( mSuspended ) + { + memset( &state, 0, sizeof(State) ); + state.connected = mConnected[ player ]; + return; + } +#endif + + XINPUT_STATE xstate; + DWORD result = XInputGetState( DWORD(player), &xstate ); + if ( result == ERROR_DEVICE_NOT_CONNECTED ) + { + ClearSlot( player, GetTickCount64() ); + } + else + { + mConnected[ player ] = true; + + state.connected = true; + state.packet = xstate.dwPacketNumber; + + WORD xbuttons = xstate.Gamepad.wButtons; + state.buttons.a = (xbuttons & XINPUT_GAMEPAD_A) != 0; + state.buttons.b = (xbuttons & XINPUT_GAMEPAD_B) != 0; + state.buttons.x = (xbuttons & XINPUT_GAMEPAD_X) != 0; + state.buttons.y = (xbuttons & XINPUT_GAMEPAD_Y) != 0; + state.buttons.leftStick = (xbuttons & XINPUT_GAMEPAD_LEFT_THUMB) != 0; + state.buttons.rightStick = (xbuttons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0; + state.buttons.leftShoulder = (xbuttons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0; + state.buttons.rightShoulder = (xbuttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0; + state.buttons.back = (xbuttons & XINPUT_GAMEPAD_BACK) != 0; + state.buttons.start = (xbuttons & XINPUT_GAMEPAD_START) != 0; + + state.dpad.up = (xbuttons & XINPUT_GAMEPAD_DPAD_UP) != 0; + state.dpad.down = (xbuttons & XINPUT_GAMEPAD_DPAD_DOWN) != 0; + state.dpad.right = (xbuttons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0; + state.dpad.left = (xbuttons & XINPUT_GAMEPAD_DPAD_LEFT) != 0; + + if ( deadZoneMode == DEAD_ZONE_NONE ) + { + state.triggers.left = ApplyLinearDeadZone( float(xstate.Gamepad.bLeftTrigger), 255.f, 0.f ); + state.triggers.right = ApplyLinearDeadZone( float(xstate.Gamepad.bRightTrigger), 255.f, 0.f ); + } + else + { + state.triggers.left = ApplyLinearDeadZone( float(xstate.Gamepad.bLeftTrigger), 255.f, float(XINPUT_GAMEPAD_TRIGGER_THRESHOLD) ); + state.triggers.right = ApplyLinearDeadZone( float(xstate.Gamepad.bRightTrigger), 255.f, float(XINPUT_GAMEPAD_TRIGGER_THRESHOLD) ); + } + + ApplyStickDeadZone( float(xstate.Gamepad.sThumbLX), float(xstate.Gamepad.sThumbLY), + deadZoneMode, 32767.f, float(XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE), + state.thumbSticks.leftX, state.thumbSticks.leftY ); + + ApplyStickDeadZone( float(xstate.Gamepad.sThumbRX), float(xstate.Gamepad.sThumbRY), + deadZoneMode, 32767.f, float(XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE), + state.thumbSticks.rightX, state.thumbSticks.rightY ); + + return; + } + } + + memset( &state, 0, sizeof(State) ); + } + + void GetCapabilities( int player, _Out_ Capabilities& caps ) + { + if ( !ThrottleRetry(player) ) + { + XINPUT_CAPABILITIES xcaps; + DWORD result = XInputGetCapabilities( DWORD(player), 0, &xcaps ); + if ( result == ERROR_DEVICE_NOT_CONNECTED ) + { + ClearSlot( player, GetTickCount64() ); + } + else + { + mConnected[ player ] = true; + + caps.connected = true; + caps.id = uint64_t( player ); + if ( xcaps.Type == XINPUT_DEVTYPE_GAMEPAD ) + { + static_assert(Capabilities::GAMEPAD == XINPUT_DEVSUBTYPE_GAMEPAD, "xinput.h mismatch"); +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + static_assert( XINPUT_DEVSUBTYPE_WHEEL == Capabilities::WHEEL, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_ARCADE_STICK == Capabilities::ARCADE_STICK, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_FLIGHT_STICK == Capabilities::FLIGHT_STICK, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_DANCE_PAD == Capabilities::DANCE_PAD, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_GUITAR == Capabilities::GUITAR, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE == Capabilities::GUITAR_ALTERNATE, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_DRUM_KIT == Capabilities::DRUM_KIT, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_GUITAR_BASS == Capabilities::GUITAR_BASS, "xinput.h mismatch"); + static_assert( XINPUT_DEVSUBTYPE_ARCADE_PAD == Capabilities::ARCADE_PAD, "xinput.h mismatch"); +#endif + + caps.gamepadType = Capabilities::Type(xcaps.SubType); + } + + return; + } + } + + memset( &caps, 0, sizeof(Capabilities) ); + } + + bool SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) + { + if ( ThrottleRetry(player) ) + { + return false; + } + + // XInput does not provide a way to set the left/right trigger impulse motors on the Xbox One Controller, + // and these motors are not present on the Xbox 360 Common Controller + UNREFERENCED_PARAMETER(leftTrigger); + UNREFERENCED_PARAMETER(rightTrigger); + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + mLeftMotor[ player ] = leftMotor; + mRightMotor[ player ] = rightMotor; + + if ( mSuspended ) + return mConnected[ player ]; +#endif + + XINPUT_VIBRATION xvibration; + xvibration.wLeftMotorSpeed = WORD( leftMotor * 0xFFFF ); + xvibration.wRightMotorSpeed = WORD( rightMotor * 0xFFFF ); + DWORD result = XInputSetState( DWORD(player), &xvibration ); + if ( result == ERROR_DEVICE_NOT_CONNECTED ) + { + ClearSlot( player, GetTickCount64() ); + return false; + } + else + { + mConnected[ player ] = true; + return (result == ERROR_SUCCESS); + } + } + + void Suspend() + { +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + XInputEnable( FALSE ); +#else + // For XInput 9.1.0, we have to emulate the behavior of XInputEnable( FALSE ) + if ( !mSuspended ) + { + for( size_t j = 0; j < XUSER_MAX_COUNT; ++j ) + { + if ( mConnected[ j ] ) + { + XINPUT_VIBRATION xvibration; + xvibration.wLeftMotorSpeed = xvibration.wRightMotorSpeed = 0; + (void)XInputSetState( DWORD(j), &xvibration ); + } + } + + mSuspended = true; + } +#endif + } + + void Resume() + { +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + XInputEnable( TRUE ); +#else + // For XInput 9.1.0, we have to emulate the behavior of XInputEnable( TRUE ) + if ( mSuspended ) + { + for( int j = 0; j < XUSER_MAX_COUNT; ++j ) + { + if ( mConnected[ j ] ) + { + XINPUT_VIBRATION xvibration; + xvibration.wLeftMotorSpeed = WORD( mLeftMotor[ j ] * 0xFFFF ); + xvibration.wRightMotorSpeed = WORD( mRightMotor[ j ] * 0xFFFF ); + DWORD result = XInputSetState( DWORD(j), &xvibration ); + if ( result == ERROR_DEVICE_NOT_CONNECTED ) + { + ClearSlot( j, GetTickCount64() ); + } + } + } + + mSuspended = false; + } +#endif + } + + GamePad* mOwner; + + static GamePad::Impl* s_gamePad; + +private: + bool mConnected[ XUSER_MAX_COUNT ]; + ULONGLONG mLastReadTime[ XUSER_MAX_COUNT ]; + +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + // Variables for emulating XInputEnable on XInput 9.1.0 + float mLeftMotor[ XUSER_MAX_COUNT ]; + float mRightMotor[ XUSER_MAX_COUNT ]; + bool mSuspended; +#endif + + bool ThrottleRetry( int player ) + { + // This function minimizes a potential performance issue with XInput on Windows when + // checking a disconnected controller slot which requires device enumeration. + // This throttling keeps checks for newly connected gamepads to about once a second + + if ( ( player < 0 ) || ( player >= XUSER_MAX_COUNT ) ) + return true; + + if ( mConnected[ player ] ) + return false; + + ULONGLONG time = GetTickCount64(); + + for( size_t j = 0; j < XUSER_MAX_COUNT; ++j ) + { + if ( !mConnected[j] ) + { + LONGLONG delta = time - mLastReadTime[j]; + + LONGLONG interval = 1000; + if ( (int)j != player ) + interval /= 4; + + if ( (delta >= 0) && (delta < interval) ) + return true; + } + } + + return false; + } + + void ClearSlot( int player, ULONGLONG time ) + { + mConnected[ player ] = false; + mLastReadTime[ player ] = time; +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) + mLeftMotor[ player ] = mRightMotor[ player ] = 0.f; +#endif + } +}; + +GamePad::Impl* GamePad::Impl::s_gamePad = nullptr; + +#endif + +#pragma warning( disable : 4355 ) + +// Public constructor. +GamePad::GamePad() + : pImpl( new Impl(this) ) +{ +} + + +// Move constructor. +GamePad::GamePad(GamePad&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ + pImpl->mOwner = this; +} + + +// Move assignment. +GamePad& GamePad::operator= (GamePad&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + pImpl->mOwner = this; + return *this; +} + + +// Public destructor. +GamePad::~GamePad() +{ +} + + +GamePad::State GamePad::GetState(int player, DeadZone deadZoneMode) +{ + State state; + pImpl->GetState(player, state, deadZoneMode); + return state; +} + + +GamePad::Capabilities GamePad::GetCapabilities(int player) +{ + Capabilities caps; + pImpl->GetCapabilities(player, caps); + return caps; +} + + +bool GamePad::SetVibration( int player, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger ) +{ + return pImpl->SetVibration( player, leftMotor, rightMotor, leftTrigger, rightTrigger ); +} + + +void GamePad::Suspend() +{ + pImpl->Suspend(); +} + + +void GamePad::Resume() +{ + pImpl->Resume(); +} + + +GamePad& GamePad::Get() +{ + if ( !Impl::s_gamePad || !Impl::s_gamePad->mOwner ) + throw std::exception( "GamePad is a singleton" ); + + return *Impl::s_gamePad->mOwner; +} + + + +//====================================================================================== +// ButtonStateTracker +//====================================================================================== + +#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.buttons.field ) | ( ( !!state.buttons.field ^ !!lastState.buttons.field ) << 1 ) ); + +void GamePad::ButtonStateTracker::Update( const GamePad::State& state ) +{ + UPDATE_BUTTON_STATE(a); + + assert( ( !state.buttons.a && !lastState.buttons.a ) == ( a == UP ) ); + assert( ( state.buttons.a && lastState.buttons.a ) == ( a == HELD ) ); + assert( ( !state.buttons.a && lastState.buttons.a ) == ( a == RELEASED ) ); + assert( ( state.buttons.a && !lastState.buttons.a ) == ( a == PRESSED ) ); + + UPDATE_BUTTON_STATE(b); + UPDATE_BUTTON_STATE(x); + UPDATE_BUTTON_STATE(y); + + UPDATE_BUTTON_STATE(leftStick); + UPDATE_BUTTON_STATE(rightStick); + + UPDATE_BUTTON_STATE(leftShoulder); + UPDATE_BUTTON_STATE(rightShoulder); + + UPDATE_BUTTON_STATE(back); + UPDATE_BUTTON_STATE(start); + + dpadUp = static_cast( ( !!state.dpad.up ) | ( ( !!state.dpad.up ^ !!lastState.dpad.up ) << 1 ) ); + dpadDown = static_cast( ( !!state.dpad.down ) | ( ( !!state.dpad.down ^ !!lastState.dpad.down ) << 1 ) ); + dpadLeft = static_cast( ( !!state.dpad.left ) | ( ( !!state.dpad.left ^ !!lastState.dpad.left ) << 1 ) ); + dpadRight = static_cast( ( !!state.dpad.right ) | ( ( !!state.dpad.right ^ !!lastState.dpad.right ) << 1 ) ); + + assert( ( !state.dpad.up && !lastState.dpad.up ) == ( dpadUp == UP ) ); + assert( ( state.dpad.up && lastState.dpad.up ) == ( dpadUp == HELD ) ); + assert( ( !state.dpad.up && lastState.dpad.up ) == ( dpadUp == RELEASED ) ); + assert( ( state.dpad.up && !lastState.dpad.up ) == ( dpadUp == PRESSED ) ); + + // Handle 'threshold' tests which emulate buttons + + bool threshold = state.IsLeftThumbStickUp(); + leftStickUp = static_cast( ( !!threshold) | ( ( !!threshold ^ !!lastState.IsLeftThumbStickUp() ) << 1 ) ); + + threshold = state.IsLeftThumbStickDown(); + leftStickDown = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickDown()) << 1)); + + threshold = state.IsLeftThumbStickLeft(); + leftStickLeft = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickLeft()) << 1)); + + threshold = state.IsLeftThumbStickRight(); + leftStickRight = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftThumbStickRight()) << 1)); + + threshold = state.IsRightThumbStickUp(); + rightStickUp = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickUp()) << 1)); + + threshold = state.IsRightThumbStickDown(); + rightStickDown = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickDown()) << 1)); + + threshold = state.IsRightThumbStickLeft(); + rightStickLeft = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickLeft()) << 1)); + + threshold = state.IsRightThumbStickRight(); + rightStickRight = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightThumbStickRight()) << 1)); + + threshold = state.IsLeftTriggerPressed(); + leftTrigger = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsLeftTriggerPressed()) << 1)); + + threshold = state.IsRightTriggerPressed(); + rightTrigger = static_cast((!!threshold) | ((!!threshold ^ !!lastState.IsRightTriggerPressed()) << 1)); + + lastState = state; +} + +#undef UPDATE_BUTTON_STATE + + +void GamePad::ButtonStateTracker::Reset() +{ + memset( this, 0, sizeof(ButtonStateTracker) ); +} diff --git a/Kits/DirectXTK12/Src/GenericMultiBuffer.h b/Kits/DirectXTK12/Src/GenericMultiBuffer.h new file mode 100644 index 00000000..1dbea5cc --- /dev/null +++ b/Kits/DirectXTK12/Src/GenericMultiBuffer.h @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------------------- +// File: GenericMultiBuffer.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" + + +namespace DirectX +{ + class GenericMultiBuffer + { + public: + GenericMultiBuffer(_In_ ID3D12Device* device, size_t numBytesPerFrame, size_t maxFrames) + : mDataStride(numBytesPerFrame) + , mNumFrames(maxFrames) + { + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(numBytesPerFrame * maxFrames); + + // Create the constant buffer. + ThrowIfFailed(device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(mResource.GetAddressOf()))); + + ThrowIfFailed(mResource->Map(0, nullptr, reinterpret_cast( &mMappedData ))); + memset(mMappedData, 0, mDataStride * maxFrames); + } + + // Get the CPU address for a given frame + void* GetPointer(_In_ size_t frameIndex) const + { + assert(frameIndex < mNumFrames); + assert(mMappedData != nullptr); + return mMappedData + ( frameIndex * mDataStride ); + } + + // Get the GPU address for a given frame + D3D12_GPU_VIRTUAL_ADDRESS GetGpuAddress(_In_ size_t frameIndex) const + { + assert(frameIndex < mNumFrames); + D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = mResource->GetGPUVirtualAddress(); + cbvGpuAddress += mDataStride * frameIndex; + return cbvGpuAddress; + } + + // Returns the resource pointer + ID3D12Resource* Resource() const { return mResource.Get(); } + + private: + Microsoft::WRL::ComPtr mResource; + uint8_t* mMappedData; + size_t mNumFrames; + size_t mDataStride; + }; +} diff --git a/Kits/DirectXTK12/Src/GeometricPrimitive.cpp b/Kits/DirectXTK12/Src/GeometricPrimitive.cpp new file mode 100644 index 00000000..104ed44f --- /dev/null +++ b/Kits/DirectXTK12/Src/GeometricPrimitive.cpp @@ -0,0 +1,434 @@ +//-------------------------------------------------------------------------------------- +// File: GeometricPrimitive.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GeometricPrimitive.h" +#include "Effects.h" +#include "CommonStates.h" +#include "DirectXHelpers.h" +#include "SharedResourcePool.h" +#include "Geometry.h" +#include "PrimitiveBatch.h" +#include "GraphicsMemory.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +// Internal GeometricPrimitive implementation class. +class GeometricPrimitive::Impl +{ +public: + void Initialize(const VertexCollection& vertices, const IndexCollection& indices); + + void Draw(_In_ ID3D12GraphicsCommandList* commandList); + + UINT mIndexCount; + GraphicsResource mIndexBuffer; + GraphicsResource mVertexBuffer; + + D3D12_VERTEX_BUFFER_VIEW mVertexBufferView; + D3D12_INDEX_BUFFER_VIEW mIndexBufferView; +}; + + +// Initializes a geometric primitive instance that will draw the specified vertex and index data. +void GeometricPrimitive::Impl::Initialize(const VertexCollection& vertices, const IndexCollection& indices) +{ + if (vertices.size() >= USHRT_MAX) + throw std::exception("Too many vertices for 16-bit index buffer"); + + // Vertex data + auto verts = reinterpret_cast(vertices.data()); + size_t vertSizeBytes = vertices.size() * sizeof(vertices[0]); + + mVertexBuffer = GraphicsMemory::Get().Allocate(vertSizeBytes); + memcpy(mVertexBuffer.Memory(), verts, vertSizeBytes); + + // Index data + auto ind = reinterpret_cast(indices.data()); + size_t indSizeBytes = indices.size() * sizeof(indices[0]); + + mIndexBuffer = GraphicsMemory::Get().Allocate(indSizeBytes); + memcpy(mIndexBuffer.Memory(), ind, indSizeBytes); + + // Record index count for draw + mIndexCount = static_cast(indices.size()); + + // Create views + mVertexBufferView.BufferLocation = mVertexBuffer.GpuAddress(); + mVertexBufferView.StrideInBytes = static_cast(sizeof(VertexCollection::value_type)); + mVertexBufferView.SizeInBytes = (UINT)mVertexBuffer.Size(); + + mIndexBufferView.BufferLocation = mIndexBuffer.GpuAddress(); + mIndexBufferView.SizeInBytes = (UINT)mIndexBuffer.Size(); + mIndexBufferView.Format = DXGI_FORMAT_R16_UINT; +} + + +// Draws the primitive. +_Use_decl_annotations_ +void GeometricPrimitive::Impl::Draw(ID3D12GraphicsCommandList* commandList) +{ + commandList->IASetVertexBuffers(0, 1, &mVertexBufferView); + commandList->IASetIndexBuffer(&mIndexBufferView); + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + commandList->DrawIndexedInstanced(mIndexCount, 1, 0, 0, 0); +} + +//-------------------------------------------------------------------------------------- +// GeometricPrimitive +//-------------------------------------------------------------------------------------- + +// Constructor. +GeometricPrimitive::GeometricPrimitive() + : pImpl(new Impl()) +{ +} + + +// Destructor. +GeometricPrimitive::~GeometricPrimitive() +{ +} + + +// Public entrypoints. +_Use_decl_annotations_ +void GeometricPrimitive::Draw(ID3D12GraphicsCommandList* commandList) +{ + pImpl->Draw(commandList); +} + + +//-------------------------------------------------------------------------------------- +// Cube (aka a Hexahedron) or Box +//-------------------------------------------------------------------------------------- + +// Creates a cube primitive. +std::unique_ptr GeometricPrimitive::CreateCube(float size, bool rhcoords) +{ + VertexCollection vertices; + IndexCollection indices; + ComputeBox(vertices, indices, XMFLOAT3(size, size, size), rhcoords, false); + + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateCube(std::vector& vertices, std::vector& indices, float size, bool rhcoords) +{ + ComputeBox(vertices, indices, XMFLOAT3(size, size, size), rhcoords, false); +} + + +// Creates a box primitive. +std::unique_ptr GeometricPrimitive::CreateBox(const XMFLOAT3& size, bool rhcoords, bool invertn) +{ + VertexCollection vertices; + IndexCollection indices; + ComputeBox(vertices, indices, size, rhcoords, invertn); + + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateBox(std::vector& vertices, std::vector& indices, const XMFLOAT3& size, bool rhcoords, bool invertn) +{ + ComputeBox(vertices, indices, size, rhcoords, invertn); +} + + +//-------------------------------------------------------------------------------------- +// Sphere +//-------------------------------------------------------------------------------------- + +// Creates a sphere primitive. +std::unique_ptr GeometricPrimitive::CreateSphere(float diameter, size_t tessellation, bool rhcoords, bool invertn) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + + ComputeSphere(vertices, indices, diameter, tessellation, rhcoords, invertn); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateSphere(std::vector& vertices, std::vector& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn) +{ + ComputeSphere(vertices, indices, diameter, tessellation, rhcoords, invertn); +} + + +//-------------------------------------------------------------------------------------- +// Geodesic sphere +//-------------------------------------------------------------------------------------- + +// Creates a geosphere primitive. +std::unique_ptr GeometricPrimitive::CreateGeoSphere(float diameter, size_t tessellation, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeGeoSphere(vertices, indices, diameter, tessellation, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateGeoSphere(std::vector& vertices, std::vector& indices, float diameter, size_t tessellation, bool rhcoords) +{ + ComputeGeoSphere(vertices, indices, diameter, tessellation, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Cylinder / Cone +//-------------------------------------------------------------------------------------- + +// Creates a cylinder primitive. +std::unique_ptr GeometricPrimitive::CreateCylinder(float height, float diameter, size_t tessellation, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeCylinder(vertices, indices, height, diameter, tessellation, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateCylinder(std::vector& vertices, std::vector& indices, float height, float diameter, size_t tessellation, bool rhcoords) +{ + ComputeCylinder(vertices, indices, height, diameter, tessellation, rhcoords); +} + + +// Creates a cone primitive. +std::unique_ptr GeometricPrimitive::CreateCone(float diameter, float height, size_t tessellation, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeCone(vertices, indices, diameter, height, tessellation, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateCone(std::vector& vertices, std::vector& indices, float diameter, float height, size_t tessellation, bool rhcoords) +{ + ComputeCone(vertices, indices, diameter, height, tessellation, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Torus +//-------------------------------------------------------------------------------------- + +// Creates a torus primitive. +std::unique_ptr GeometricPrimitive::CreateTorus(float diameter, float thickness, size_t tessellation, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeTorus(vertices, indices, diameter, thickness, tessellation, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateTorus(std::vector& vertices, std::vector& indices, float diameter, float thickness, size_t tessellation, bool rhcoords) +{ + ComputeTorus(vertices, indices, diameter, thickness, tessellation, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Tetrahedron +//-------------------------------------------------------------------------------------- + +std::unique_ptr GeometricPrimitive::CreateTetrahedron(float size, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeTetrahedron(vertices, indices, size, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateTetrahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords) +{ + ComputeTetrahedron(vertices, indices, size, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Octahedron +//-------------------------------------------------------------------------------------- + +std::unique_ptr GeometricPrimitive::CreateOctahedron(float size, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeOctahedron(vertices, indices, size, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateOctahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords) +{ + ComputeOctahedron(vertices, indices, size, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Dodecahedron +//-------------------------------------------------------------------------------------- + +std::unique_ptr GeometricPrimitive::CreateDodecahedron(float size, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeDodecahedron(vertices, indices, size, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateDodecahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords) +{ + ComputeDodecahedron(vertices, indices, size, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Icosahedron +//-------------------------------------------------------------------------------------- + +std::unique_ptr GeometricPrimitive::CreateIcosahedron(float size, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeIcosahedron(vertices, indices, size, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateIcosahedron(std::vector& vertices, std::vector& indices, float size, bool rhcoords) +{ + ComputeIcosahedron(vertices, indices, size, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Teapot +//-------------------------------------------------------------------------------------- + +// Creates a teapot primitive. +std::unique_ptr GeometricPrimitive::CreateTeapot(float size, size_t tessellation, bool rhcoords) +{ + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + VertexCollection vertices; + IndexCollection indices; + ComputeTeapot(vertices, indices, size, tessellation, rhcoords); + + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} + +void GeometricPrimitive::CreateTeapot(std::vector& vertices, std::vector& indices, float size, size_t tessellation, bool rhcoords) +{ + ComputeTeapot(vertices, indices, size, tessellation, rhcoords); +} + + +//-------------------------------------------------------------------------------------- +// Custom +//-------------------------------------------------------------------------------------- + +std::unique_ptr GeometricPrimitive::CreateCustom(const std::vector& vertices, const std::vector& indices) +{ + // Extra validation + if (vertices.empty() || indices.empty()) + throw std::exception("Requires both vertices and indices"); + + if (indices.size() % 3) + throw std::exception("Expected triangular faces"); + + size_t nVerts = vertices.size(); + if (nVerts >= USHRT_MAX) + throw std::exception("Too many vertices for 16-bit index buffer"); + + for (auto it = indices.cbegin(); it != indices.cend(); ++it) + { + if (*it >= nVerts) + { + throw std::exception("Index not in vertices list"); + } + } + // Create the primitive object. + std::unique_ptr primitive(new GeometricPrimitive()); + + // copy geometry + primitive->pImpl->Initialize(vertices, indices); + + return primitive; +} diff --git a/Kits/DirectXTK12/Src/Geometry.cpp b/Kits/DirectXTK12/Src/Geometry.cpp new file mode 100644 index 00000000..6b5c3b80 --- /dev/null +++ b/Kits/DirectXTK12/Src/Geometry.cpp @@ -0,0 +1,1184 @@ +//-------------------------------------------------------------------------------------- +// File: Geometry.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Geometry.h" +#include "Bezier.h" + +using namespace DirectX; + +namespace +{ + const float SQRT2 = 1.41421356237309504880f; + const float SQRT3 = 1.73205080756887729352f; + const float SQRT6 = 2.44948974278317809820f; + + inline void CheckIndexOverflow(size_t value) + { + // Use >=, not > comparison, because some D3D level 9_x hardware does not support 0xFFFF index values. + if (value >= USHRT_MAX) + throw std::exception("Index value out of range: cannot tesselate primitive so finely"); + } + + + // Collection types used when generating the geometry. + inline void index_push_back(IndexCollection& indices, size_t value) + { + CheckIndexOverflow(value); + indices.push_back((uint16_t)value); + } + + + // Helper for flipping winding of geometric primitives for LH vs. RH coords + inline void ReverseWinding(IndexCollection& indices, VertexCollection& vertices) + { + assert((indices.size() % 3) == 0); + for (auto it = indices.begin(); it != indices.end(); it += 3) + { + std::swap(*it, *(it + 2)); + } + + for (auto it = vertices.begin(); it != vertices.end(); ++it) + { + it->textureCoordinate.x = (1.f - it->textureCoordinate.x); + } + } + + + // Helper for inverting normals of geometric primitives for 'inside' vs. 'outside' viewing + inline void InvertNormals(VertexCollection& vertices) + { + for (auto it = vertices.begin(); it != vertices.end(); ++it) + { + it->normal.x = -it->normal.x; + it->normal.y = -it->normal.y; + it->normal.z = -it->normal.z; + } + } +} + + +//-------------------------------------------------------------------------------------- +// Cube (aka a Hexahedron) or Box +//-------------------------------------------------------------------------------------- +void DirectX::ComputeBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords, bool invertn) +{ + vertices.clear(); + indices.clear(); + + // A box has six faces, each one pointing in a different direction. + const int FaceCount = 6; + + static const XMVECTORF32 faceNormals[FaceCount] = + { + { 0, 0, 1 }, + { 0, 0, -1 }, + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + }; + + static const XMVECTORF32 textureCoordinates[4] = + { + { 1, 0 }, + { 1, 1 }, + { 0, 1 }, + { 0, 0 }, + }; + + XMVECTOR tsize = XMLoadFloat3(&size); + tsize = XMVectorDivide(tsize, g_XMTwo); + + // Create each face in turn. + for (int i = 0; i < FaceCount; i++) + { + XMVECTOR normal = faceNormals[i]; + + // Get two vectors perpendicular both to the face normal and to each other. + XMVECTOR basis = (i >= 4) ? g_XMIdentityR2 : g_XMIdentityR1; + + XMVECTOR side1 = XMVector3Cross(normal, basis); + XMVECTOR side2 = XMVector3Cross(normal, side1); + + // Six indices (two triangles) per face. + size_t vbase = vertices.size(); + index_push_back(indices, vbase + 0); + index_push_back(indices, vbase + 1); + index_push_back(indices, vbase + 2); + + index_push_back(indices, vbase + 0); + index_push_back(indices, vbase + 2); + index_push_back(indices, vbase + 3); + + // Four vertices per face. + vertices.push_back(VertexPositionNormalTexture((normal - side1 - side2) * tsize, normal, textureCoordinates[0])); + vertices.push_back(VertexPositionNormalTexture((normal - side1 + side2) * tsize, normal, textureCoordinates[1])); + vertices.push_back(VertexPositionNormalTexture((normal + side1 + side2) * tsize, normal, textureCoordinates[2])); + vertices.push_back(VertexPositionNormalTexture((normal + side1 - side2) * tsize, normal, textureCoordinates[3])); + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); + + if (invertn) + InvertNormals(vertices); +} + + +//-------------------------------------------------------------------------------------- +// Sphere +//-------------------------------------------------------------------------------------- +void DirectX::ComputeSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + size_t verticalSegments = tessellation; + size_t horizontalSegments = tessellation * 2; + + float radius = diameter / 2; + + // Create rings of vertices at progressively higher latitudes. + for (size_t i = 0; i <= verticalSegments; i++) + { + float v = 1 - (float)i / verticalSegments; + + float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; + float dy, dxz; + + XMScalarSinCos(&dy, &dxz, latitude); + + // Create a single ring of vertices at this latitude. + for (size_t j = 0; j <= horizontalSegments; j++) + { + float u = (float)j / horizontalSegments; + + float longitude = j * XM_2PI / horizontalSegments; + float dx, dz; + + XMScalarSinCos(&dx, &dz, longitude); + + dx *= dxz; + dz *= dxz; + + XMVECTOR normal = XMVectorSet(dx, dy, dz, 0); + XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); + + vertices.push_back(VertexPositionNormalTexture(normal * radius, normal, textureCoordinate)); + } + } + + // Fill the index buffer with triangles joining each pair of latitude rings. + size_t stride = horizontalSegments + 1; + + for (size_t i = 0; i < verticalSegments; i++) + { + for (size_t j = 0; j <= horizontalSegments; j++) + { + size_t nextI = i + 1; + size_t nextJ = (j + 1) % stride; + + index_push_back(indices, i * stride + j); + index_push_back(indices, nextI * stride + j); + index_push_back(indices, i * stride + nextJ); + + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + j); + index_push_back(indices, nextI * stride + nextJ); + } + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); + + if (invertn) + InvertNormals(vertices); +} + + +//-------------------------------------------------------------------------------------- +// Geodesic sphere +//-------------------------------------------------------------------------------------- +void DirectX::ComputeGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + // An undirected edge between two vertices, represented by a pair of indexes into a vertex array. + // Becuse this edge is undirected, (a,b) is the same as (b,a). + typedef std::pair UndirectedEdge; + + // Makes an undirected edge. Rather than overloading comparison operators to give us the (a,b)==(b,a) property, + // we'll just ensure that the larger of the two goes first. This'll simplify things greatly. + auto makeUndirectedEdge = [](uint16_t a, uint16_t b) + { + return std::make_pair(std::max(a, b), std::min(a, b)); + }; + + // Key: an edge + // Value: the index of the vertex which lies midway between the two vertices pointed to by the key value + // This map is used to avoid duplicating vertices when subdividing triangles along edges. + typedef std::map EdgeSubdivisionMap; + + + static const XMFLOAT3 OctahedronVertices[] = + { + // when looking down the negative z-axis (into the screen) + XMFLOAT3(0, 1, 0), // 0 top + XMFLOAT3(0, 0, -1), // 1 front + XMFLOAT3(1, 0, 0), // 2 right + XMFLOAT3(0, 0, 1), // 3 back + XMFLOAT3(-1, 0, 0), // 4 left + XMFLOAT3(0, -1, 0), // 5 bottom + }; + static const uint16_t OctahedronIndices[] = + { + 0, 1, 2, // top front-right face + 0, 2, 3, // top back-right face + 0, 3, 4, // top back-left face + 0, 4, 1, // top front-left face + 5, 1, 4, // bottom front-left face + 5, 4, 3, // bottom back-left face + 5, 3, 2, // bottom back-right face + 5, 2, 1, // bottom front-right face + }; + + const float radius = diameter / 2.0f; + + // Start with an octahedron; copy the data into the vertex/index collection. + + std::vector vertexPositions(std::begin(OctahedronVertices), std::end(OctahedronVertices)); + + indices.insert(indices.begin(), std::begin(OctahedronIndices), std::end(OctahedronIndices)); + + // We know these values by looking at the above index list for the octahedron. Despite the subdivisions that are + // about to go on, these values aren't ever going to change because the vertices don't move around in the array. + // We'll need these values later on to fix the singularities that show up at the poles. + const uint16_t northPoleIndex = 0; + const uint16_t southPoleIndex = 5; + + for (size_t iSubdivision = 0; iSubdivision < tessellation; ++iSubdivision) + { + assert(indices.size() % 3 == 0); // sanity + + // We use this to keep track of which edges have already been subdivided. + EdgeSubdivisionMap subdividedEdges; + + // The new index collection after subdivision. + IndexCollection newIndices; + + const size_t triangleCount = indices.size() / 3; + for (size_t iTriangle = 0; iTriangle < triangleCount; ++iTriangle) + { + // For each edge on this triangle, create a new vertex in the middle of that edge. + // The winding order of the triangles we output are the same as the winding order of the inputs. + + // Indices of the vertices making up this triangle + uint16_t iv0 = indices[iTriangle * 3 + 0]; + uint16_t iv1 = indices[iTriangle * 3 + 1]; + uint16_t iv2 = indices[iTriangle * 3 + 2]; + + // Get the new vertices + XMFLOAT3 v01; // vertex on the midpoint of v0 and v1 + XMFLOAT3 v12; // ditto v1 and v2 + XMFLOAT3 v20; // ditto v2 and v0 + uint16_t iv01; // index of v01 + uint16_t iv12; // index of v12 + uint16_t iv20; // index of v20 + + // Function that, when given the index of two vertices, creates a new vertex at the midpoint of those vertices. + auto divideEdge = [&](uint16_t i0, uint16_t i1, XMFLOAT3& outVertex, uint16_t& outIndex) + { + const UndirectedEdge edge = makeUndirectedEdge(i0, i1); + + // Check to see if we've already generated this vertex + auto it = subdividedEdges.find(edge); + if (it != subdividedEdges.end()) + { + // We've already generated this vertex before + outIndex = it->second; // the index of this vertex + outVertex = vertexPositions[outIndex]; // and the vertex itself + } + else + { + // Haven't generated this vertex before: so add it now + + // outVertex = (vertices[i0] + vertices[i1]) / 2 + XMStoreFloat3( + &outVertex, + XMVectorScale( + XMVectorAdd(XMLoadFloat3(&vertexPositions[i0]), XMLoadFloat3(&vertexPositions[i1])), + 0.5f + ) + ); + + outIndex = static_cast(vertexPositions.size()); + CheckIndexOverflow(outIndex); + vertexPositions.push_back(outVertex); + + // Now add it to the map. + subdividedEdges.insert(std::make_pair(edge, outIndex)); + } + }; + + // Add/get new vertices and their indices + divideEdge(iv0, iv1, v01, iv01); + divideEdge(iv1, iv2, v12, iv12); + divideEdge(iv0, iv2, v20, iv20); + + // Add the new indices. We have four new triangles from our original one: + // v0 + // o + // /a\ + // v20 o---o v01 + // /b\c/d\ + // v2 o---o---o v1 + // v12 + const uint16_t indicesToAdd[] = + { + iv0, iv01, iv20, // a + iv20, iv12, iv2, // b + iv20, iv01, iv12, // c + iv01, iv1, iv12, // d + }; + newIndices.insert(newIndices.end(), std::begin(indicesToAdd), std::end(indicesToAdd)); + } + + indices = std::move(newIndices); + } + + // Now that we've completed subdivision, fill in the final vertex collection + vertices.reserve(vertexPositions.size()); + for (auto it = vertexPositions.begin(); it != vertexPositions.end(); ++it) + { + auto vertexValue = *it; + + auto normal = XMVector3Normalize(XMLoadFloat3(&vertexValue)); + auto pos = XMVectorScale(normal, radius); + + XMFLOAT3 normalFloat3; + XMStoreFloat3(&normalFloat3, normal); + + // calculate texture coordinates for this vertex + float longitude = atan2(normalFloat3.x, -normalFloat3.z); + float latitude = acos(normalFloat3.y); + + float u = longitude / XM_2PI + 0.5f; + float v = latitude / XM_PI; + + auto texcoord = XMVectorSet(1.0f - u, v, 0.0f, 0.0f); + vertices.push_back(VertexPositionNormalTexture(pos, normal, texcoord)); + } + + // There are a couple of fixes to do. One is a texture coordinate wraparound fixup. At some point, there will be + // a set of triangles somewhere in the mesh with texture coordinates such that the wraparound across 0.0/1.0 + // occurs across that triangle. Eg. when the left hand side of the triangle has a U coordinate of 0.98 and the + // right hand side has a U coordinate of 0.0. The intent is that such a triangle should render with a U of 0.98 to + // 1.0, not 0.98 to 0.0. If we don't do this fixup, there will be a visible seam across one side of the sphere. + // + // Luckily this is relatively easy to fix. There is a straight edge which runs down the prime meridian of the + // completed sphere. If you imagine the vertices along that edge, they circumscribe a semicircular arc starting at + // y=1 and ending at y=-1, and sweeping across the range of z=0 to z=1. x stays zero. It's along this edge that we + // need to duplicate our vertices - and provide the correct texture coordinates. + size_t preFixupVertexCount = vertices.size(); + for (size_t i = 0; i < preFixupVertexCount; ++i) + { + // This vertex is on the prime meridian if position.x and texcoord.u are both zero (allowing for small epsilon). + bool isOnPrimeMeridian = XMVector2NearEqual( + XMVectorSet(vertices[i].position.x, vertices[i].textureCoordinate.x, 0.0f, 0.0f), + XMVectorZero(), + XMVectorSplatEpsilon()); + + if (isOnPrimeMeridian) + { + size_t newIndex = vertices.size(); // the index of this vertex that we're about to add + CheckIndexOverflow(newIndex); + + // copy this vertex, correct the texture coordinate, and add the vertex + VertexPositionNormalTexture v = vertices[i]; + v.textureCoordinate.x = 1.0f; + vertices.push_back(v); + + // Now find all the triangles which contain this vertex and update them if necessary + for (size_t j = 0; j < indices.size(); j += 3) + { + uint16_t* triIndex0 = &indices[j + 0]; + uint16_t* triIndex1 = &indices[j + 1]; + uint16_t* triIndex2 = &indices[j + 2]; + + if (*triIndex0 == i) + { + // nothing; just keep going + } + else if (*triIndex1 == i) + { + std::swap(triIndex0, triIndex1); // swap the pointers (not the values) + } + else if (*triIndex2 == i) + { + std::swap(triIndex0, triIndex2); // swap the pointers (not the values) + } + else + { + // this triangle doesn't use the vertex we're interested in + continue; + } + + // If we got to this point then triIndex0 is the pointer to the index to the vertex we're looking at + assert(*triIndex0 == i); + assert(*triIndex1 != i && *triIndex2 != i); // assume no degenerate triangles + + const VertexPositionNormalTexture& v0 = vertices[*triIndex0]; + const VertexPositionNormalTexture& v1 = vertices[*triIndex1]; + const VertexPositionNormalTexture& v2 = vertices[*triIndex2]; + + // check the other two vertices to see if we might need to fix this triangle + + if (abs(v0.textureCoordinate.x - v1.textureCoordinate.x) > 0.5f || + abs(v0.textureCoordinate.x - v2.textureCoordinate.x) > 0.5f) + { + // yep; replace the specified index to point to the new, corrected vertex + *triIndex0 = static_cast(newIndex); + } + } + } + } + + // And one last fix we need to do: the poles. A common use-case of a sphere mesh is to map a rectangular texture onto + // it. If that happens, then the poles become singularities which map the entire top and bottom rows of the texture + // onto a single point. In general there's no real way to do that right. But to match the behavior of non-geodesic + // spheres, we need to duplicate the pole vertex for every triangle that uses it. This will introduce seams near the + // poles, but reduce stretching. + auto fixPole = [&](size_t poleIndex) + { + auto poleVertex = vertices[poleIndex]; + bool overwrittenPoleVertex = false; // overwriting the original pole vertex saves us one vertex + + for (size_t i = 0; i < indices.size(); i += 3) + { + // These pointers point to the three indices which make up this triangle. pPoleIndex is the pointer to the + // entry in the index array which represents the pole index, and the other two pointers point to the other + // two indices making up this triangle. + uint16_t* pPoleIndex; + uint16_t* pOtherIndex0; + uint16_t* pOtherIndex1; + if (indices[i + 0] == poleIndex) + { + pPoleIndex = &indices[i + 0]; + pOtherIndex0 = &indices[i + 1]; + pOtherIndex1 = &indices[i + 2]; + } + else if (indices[i + 1] == poleIndex) + { + pPoleIndex = &indices[i + 1]; + pOtherIndex0 = &indices[i + 2]; + pOtherIndex1 = &indices[i + 0]; + } + else if (indices[i + 2] == poleIndex) + { + pPoleIndex = &indices[i + 2]; + pOtherIndex0 = &indices[i + 0]; + pOtherIndex1 = &indices[i + 1]; + } + else + { + continue; + } + + const auto& otherVertex0 = vertices[*pOtherIndex0]; + const auto& otherVertex1 = vertices[*pOtherIndex1]; + + // Calculate the texcoords for the new pole vertex, add it to the vertices and update the index + VertexPositionNormalTexture newPoleVertex = poleVertex; + newPoleVertex.textureCoordinate.x = (otherVertex0.textureCoordinate.x + otherVertex1.textureCoordinate.x) / 2; + newPoleVertex.textureCoordinate.y = poleVertex.textureCoordinate.y; + + if (!overwrittenPoleVertex) + { + vertices[poleIndex] = newPoleVertex; + overwrittenPoleVertex = true; + } + else + { + CheckIndexOverflow(vertices.size()); + + *pPoleIndex = static_cast(vertices.size()); + vertices.push_back(newPoleVertex); + } + } + }; + + fixPole(northPoleIndex); + fixPole(southPoleIndex); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Cylinder / Cone +//-------------------------------------------------------------------------------------- +namespace +{ + // Helper computes a point on a unit circle, aligned to the x/z plane and centered on the origin. + inline XMVECTOR GetCircleVector(size_t i, size_t tessellation) + { + float angle = i * XM_2PI / tessellation; + float dx, dz; + + XMScalarSinCos(&dx, &dz, angle); + + XMVECTORF32 v = { dx, 0, dz, 0 }; + return v; + } + + inline XMVECTOR GetCircleTangent(size_t i, size_t tessellation) + { + float angle = (i * XM_2PI / tessellation) + XM_PIDIV2; + float dx, dz; + + XMScalarSinCos(&dx, &dz, angle); + + XMVECTORF32 v = { dx, 0, dz, 0 }; + return v; + } + + + // Helper creates a triangle fan to close the end of a cylinder / cone + void CreateCylinderCap(VertexCollection& vertices, IndexCollection& indices, size_t tessellation, float height, float radius, bool isTop) + { + // Create cap indices. + for (size_t i = 0; i < tessellation - 2; i++) + { + size_t i1 = (i + 1) % tessellation; + size_t i2 = (i + 2) % tessellation; + + if (isTop) + { + std::swap(i1, i2); + } + + size_t vbase = vertices.size(); + index_push_back(indices, vbase); + index_push_back(indices, vbase + i1); + index_push_back(indices, vbase + i2); + } + + // Which end of the cylinder is this? + XMVECTOR normal = g_XMIdentityR1; + XMVECTOR textureScale = g_XMNegativeOneHalf; + + if (!isTop) + { + normal = -normal; + textureScale *= g_XMNegateX; + } + + // Create cap vertices. + for (size_t i = 0; i < tessellation; i++) + { + XMVECTOR circleVector = GetCircleVector(i, tessellation); + + XMVECTOR position = (circleVector * radius) + (normal * height); + + XMVECTOR textureCoordinate = XMVectorMultiplyAdd(XMVectorSwizzle<0, 2, 3, 3>(circleVector), textureScale, g_XMOneHalf); + + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + } + } +} + +void DirectX::ComputeCylinder(VertexCollection& vertices, IndexCollection& indices, float height, float diameter, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + height /= 2; + + XMVECTOR topOffset = g_XMIdentityR1 * height; + + float radius = diameter / 2; + size_t stride = tessellation + 1; + + // Create a ring of triangles around the outside of the cylinder. + for (size_t i = 0; i <= tessellation; i++) + { + XMVECTOR normal = GetCircleVector(i, tessellation); + + XMVECTOR sideOffset = normal * radius; + + float u = (float)i / tessellation; + + XMVECTOR textureCoordinate = XMLoadFloat(&u); + + vertices.push_back(VertexPositionNormalTexture(sideOffset + topOffset, normal, textureCoordinate)); + vertices.push_back(VertexPositionNormalTexture(sideOffset - topOffset, normal, textureCoordinate + g_XMIdentityR1)); + + index_push_back(indices, i * 2); + index_push_back(indices, (i * 2 + 2) % (stride * 2)); + index_push_back(indices, i * 2 + 1); + + index_push_back(indices, i * 2 + 1); + index_push_back(indices, (i * 2 + 2) % (stride * 2)); + index_push_back(indices, (i * 2 + 3) % (stride * 2)); + } + + // Create flat triangle fan caps to seal the top and bottom. + CreateCylinderCap(vertices, indices, tessellation, height, radius, true); + CreateCylinderCap(vertices, indices, tessellation, height, radius, false); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +// Creates a cone primitive. +void DirectX::ComputeCone(VertexCollection& vertices, IndexCollection& indices, float diameter, float height, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + height /= 2; + + XMVECTOR topOffset = g_XMIdentityR1 * height; + + float radius = diameter / 2; + size_t stride = tessellation + 1; + + // Create a ring of triangles around the outside of the cone. + for (size_t i = 0; i <= tessellation; i++) + { + XMVECTOR circlevec = GetCircleVector(i, tessellation); + + XMVECTOR sideOffset = circlevec * radius; + + float u = (float)i / tessellation; + + XMVECTOR textureCoordinate = XMLoadFloat(&u); + + XMVECTOR pt = sideOffset - topOffset; + + XMVECTOR normal = XMVector3Cross(GetCircleTangent(i, tessellation), topOffset - pt); + normal = XMVector3Normalize(normal); + + // Duplicate the top vertex for distinct normals + vertices.push_back(VertexPositionNormalTexture(topOffset, normal, g_XMZero)); + vertices.push_back(VertexPositionNormalTexture(pt, normal, textureCoordinate + g_XMIdentityR1)); + + index_push_back(indices, i * 2); + index_push_back(indices, (i * 2 + 3) % (stride * 2)); + index_push_back(indices, (i * 2 + 1) % (stride * 2)); + } + + // Create flat triangle fan caps to seal the bottom. + CreateCylinderCap(vertices, indices, tessellation, height, radius, false); + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Torus +//-------------------------------------------------------------------------------------- +void DirectX::ComputeTorus(VertexCollection& vertices, IndexCollection& indices, float diameter, float thickness, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + size_t stride = tessellation + 1; + + // First we loop around the main ring of the torus. + for (size_t i = 0; i <= tessellation; i++) + { + float u = (float)i / tessellation; + + float outerAngle = i * XM_2PI / tessellation - XM_PIDIV2; + + // Create a transform matrix that will align geometry to + // slice perpendicularly though the current ring position. + XMMATRIX transform = XMMatrixTranslation(diameter / 2, 0, 0) * XMMatrixRotationY(outerAngle); + + // Now we loop along the other axis, around the side of the tube. + for (size_t j = 0; j <= tessellation; j++) + { + float v = 1 - (float)j / tessellation; + + float innerAngle = j * XM_2PI / tessellation + XM_PI; + float dx, dy; + + XMScalarSinCos(&dy, &dx, innerAngle); + + // Create a vertex. + XMVECTOR normal = XMVectorSet(dx, dy, 0, 0); + XMVECTOR position = normal * thickness / 2; + XMVECTOR textureCoordinate = XMVectorSet(u, v, 0, 0); + + position = XMVector3Transform(position, transform); + normal = XMVector3TransformNormal(normal, transform); + + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + + // And create indices for two triangles. + size_t nextI = (i + 1) % stride; + size_t nextJ = (j + 1) % stride; + + index_push_back(indices, i * stride + j); + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + j); + + index_push_back(indices, i * stride + nextJ); + index_push_back(indices, nextI * stride + nextJ); + index_push_back(indices, nextI * stride + j); + } + } + + // Build RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} + + +//-------------------------------------------------------------------------------------- +// Tetrahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const XMVECTORF32 verts[4] = + { + { 0.f, 0.f, 1.f }, + { 2.f*SQRT2 / 3.f, 0.f, -1.f / 3.f }, + { -SQRT2 / 3.f, SQRT6 / 3.f, -1.f / 3.f }, + { -SQRT2 / 3.f, -SQRT6 / 3.f, -1.f / 3.f } + }; + + static const uint32_t faces[4 * 3] = + { + 0, 1, 2, + 0, 2, 3, + 0, 3, 1, + 1, 3, 2, + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1 */)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 4 * 3); + assert(indices.size() == 4 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Octahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeOctahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const XMVECTORF32 verts[6] = + { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 } + }; + + static const uint32_t faces[8 * 3] = + { + 4, 0, 2, + 4, 2, 1, + 4, 1, 3, + 4, 3, 0, + 5, 2, 0, + 5, 1, 2, + 5, 3, 1, + 5, 0, 3 + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1*/)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 8 * 3); + assert(indices.size() == 8 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Dodecahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const float a = 1.f / SQRT3; + static const float b = 0.356822089773089931942f; // sqrt( ( 3 - sqrt(5) ) / 6 ) + static const float c = 0.934172358962715696451f; // sqrt( ( 3 + sqrt(5) ) / 6 ); + + static const XMVECTORF32 verts[20] = + { + { a, a, a }, + { a, a, -a }, + { a, -a, a }, + { a, -a, -a }, + { -a, a, a }, + { -a, a, -a }, + { -a, -a, a }, + { -a, -a, -a }, + { b, c, 0 }, + { -b, c, 0 }, + { b, -c, 0 }, + { -b, -c, 0 }, + { c, 0, b }, + { c, 0, -b }, + { -c, 0, b }, + { -c, 0, -b }, + { 0, b, c }, + { 0, -b, c }, + { 0, b, -c }, + { 0, -b, -c } + }; + + static const uint32_t faces[12 * 5] = + { + 0, 8, 9, 4, 16, + 0, 16, 17, 2, 12, + 12, 2, 10, 3, 13, + 9, 5, 15, 14, 4, + 3, 19, 18, 1, 13, + 7, 11, 6, 14, 15, + 0, 12, 13, 1, 8, + 8, 1, 18, 5, 9, + 16, 4, 14, 6, 17, + 6, 11, 10, 2, 17, + 7, 15, 5, 18, 19, + 7, 19, 3, 10, 11, + }; + + static const XMVECTORF32 textureCoordinates[5] = + { + { 0.654508f, 0.0244717f }, + { 0.0954915f, 0.206107f }, + { 0.0954915f, 0.793893f }, + { 0.654508f, 0.975528f }, + { 1.f, 0.5f } + }; + + static const uint32_t textureIndex[12][5] = + { + { 0, 1, 2, 3, 4 }, + { 2, 3, 4, 0, 1 }, + { 4, 0, 1, 2, 3 }, + { 1, 2, 3, 4, 0 }, + { 2, 3, 4, 0, 1 }, + { 0, 1, 2, 3, 4 }, + { 1, 2, 3, 4, 0 }, + { 4, 0, 1, 2, 3 }, + { 4, 0, 1, 2, 3 }, + { 1, 2, 3, 4, 0 }, + { 0, 1, 2, 3, 4 }, + { 2, 3, 4, 0, 1 }, + }; + + size_t t = 0; + for (size_t j = 0; j < _countof(faces); j += 5, ++t) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + uint32_t v3 = faces[j + 3]; + uint32_t v4 = faces[j + 4]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + index_push_back(indices, base); + index_push_back(indices, base + 2); + index_push_back(indices, base + 3); + + index_push_back(indices, base); + index_push_back(indices, base + 3); + index_push_back(indices, base + 4); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][0]])); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][1]])); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][2]])); + + position = XMVectorScale(verts[v3], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][3]])); + + position = XMVectorScale(verts[v4], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinates[textureIndex[t][4]])); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 12 * 5); + assert(indices.size() == 12 * 3 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Icosahedron +//-------------------------------------------------------------------------------------- +void DirectX::ComputeIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + static const float t = 1.618033988749894848205f; // (1 + sqrt(5)) / 2 + static const float t2 = 1.519544995837552493271f; // sqrt( 1 + sqr( (1 + sqrt(5)) / 2 ) ) + + static const XMVECTORF32 verts[12] = + { + { t / t2, 1.f / t2, 0 }, + { -t / t2, 1.f / t2, 0 }, + { t / t2, -1.f / t2, 0 }, + { -t / t2, -1.f / t2, 0 }, + { 1.f / t2, 0, t / t2 }, + { 1.f / t2, 0, -t / t2 }, + { -1.f / t2, 0, t / t2 }, + { -1.f / t2, 0, -t / t2 }, + { 0, t / t2, 1.f / t2 }, + { 0, -t / t2, 1.f / t2 }, + { 0, t / t2, -1.f / t2 }, + { 0, -t / t2, -1.f / t2 } + }; + + static const uint32_t faces[20 * 3] = + { + 0, 8, 4, + 0, 5, 10, + 2, 4, 9, + 2, 11, 5, + 1, 6, 8, + 1, 10, 7, + 3, 9, 6, + 3, 7, 11, + 0, 10, 8, + 1, 8, 10, + 2, 9, 11, + 3, 11, 9, + 4, 2, 0, + 5, 0, 2, + 6, 1, 3, + 7, 3, 1, + 8, 6, 4, + 9, 4, 6, + 10, 5, 7, + 11, 7, 5 + }; + + for (size_t j = 0; j < _countof(faces); j += 3) + { + uint32_t v0 = faces[j]; + uint32_t v1 = faces[j + 1]; + uint32_t v2 = faces[j + 2]; + + XMVECTOR normal = XMVector3Cross(verts[v1].v - verts[v0].v, + verts[v2].v - verts[v0].v); + normal = XMVector3Normalize(normal); + + size_t base = vertices.size(); + index_push_back(indices, base); + index_push_back(indices, base + 1); + index_push_back(indices, base + 2); + + // Duplicate vertices to use face normals + XMVECTOR position = XMVectorScale(verts[v0], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMZero /* 0, 0 */)); + + position = XMVectorScale(verts[v1], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR0 /* 1, 0 */)); + + position = XMVectorScale(verts[v2], size); + vertices.push_back(VertexPositionNormalTexture(position, normal, g_XMIdentityR1 /* 0, 1 */)); + } + + // Built LH above + if (rhcoords) + ReverseWinding(indices, vertices); + + assert(vertices.size() == 20 * 3); + assert(indices.size() == 20 * 3); +} + + +//-------------------------------------------------------------------------------------- +// Teapot +//-------------------------------------------------------------------------------------- + +// Include the teapot control point data. +namespace +{ +#include "TeapotData.inc" + + // Tessellates the specified bezier patch. + void XM_CALLCONV TessellatePatch(VertexCollection& vertices, IndexCollection& indices, TeapotPatch const& patch, size_t tessellation, FXMVECTOR scale, bool isMirrored) + { + // Look up the 16 control points for this patch. + XMVECTOR controlPoints[16]; + + for (int i = 0; i < 16; i++) + { + controlPoints[i] = TeapotControlPoints[patch.indices[i]] * scale; + } + + // Create the index data. + size_t vbase = vertices.size(); + Bezier::CreatePatchIndices(tessellation, isMirrored, [&](size_t index) + { + index_push_back(indices, vbase + index); + }); + + // Create the vertex data. + Bezier::CreatePatchVertices(controlPoints, tessellation, isMirrored, [&](FXMVECTOR position, FXMVECTOR normal, FXMVECTOR textureCoordinate) + { + vertices.push_back(VertexPositionNormalTexture(position, normal, textureCoordinate)); + }); + } +} + + +// Creates a teapot primitive. +void DirectX::ComputeTeapot(VertexCollection& vertices, IndexCollection& indices, float size, size_t tessellation, bool rhcoords) +{ + vertices.clear(); + indices.clear(); + + if (tessellation < 1) + throw std::out_of_range("tesselation parameter out of range"); + + XMVECTOR scaleVector = XMVectorReplicate(size); + + XMVECTOR scaleNegateX = scaleVector * g_XMNegateX; + XMVECTOR scaleNegateZ = scaleVector * g_XMNegateZ; + XMVECTOR scaleNegateXZ = scaleVector * g_XMNegateX * g_XMNegateZ; + + for (int i = 0; i < sizeof(TeapotPatches) / sizeof(TeapotPatches[0]); i++) + { + TeapotPatch const& patch = TeapotPatches[i]; + + // Because the teapot is symmetrical from left to right, we only store + // data for one side, then tessellate each patch twice, mirroring in X. + TessellatePatch(vertices, indices, patch, tessellation, scaleVector, false); + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateX, true); + + if (patch.mirrorZ) + { + // Some parts of the teapot (the body, lid, and rim, but not the + // handle or spout) are also symmetrical from front to back, so + // we tessellate them four times, mirroring in Z as well as X. + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateZ, true); + TessellatePatch(vertices, indices, patch, tessellation, scaleNegateXZ, false); + } + } + + // Built RH above + if (!rhcoords) + ReverseWinding(indices, vertices); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/Geometry.h b/Kits/DirectXTK12/Src/Geometry.h new file mode 100644 index 00000000..2afc7d0f --- /dev/null +++ b/Kits/DirectXTK12/Src/Geometry.h @@ -0,0 +1,32 @@ +//-------------------------------------------------------------------------------------- +// File: Geometry.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "VertexTypes.h" + +namespace DirectX +{ + typedef std::vector VertexCollection; + typedef std::vector IndexCollection; + + void ComputeBox(VertexCollection& vertices, IndexCollection& indices, const XMFLOAT3& size, bool rhcoords, bool invertn); + void ComputeSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords, bool invertn); + void ComputeGeoSphere(VertexCollection& vertices, IndexCollection& indices, float diameter, size_t tessellation, bool rhcoords); + void ComputeCylinder(VertexCollection& vertices, IndexCollection& indices, float height, float diameter, size_t tessellation, bool rhcoords); + void ComputeCone(VertexCollection& vertices, IndexCollection& indices, float diameter, float height, size_t tessellation, bool rhcoords); + void ComputeTorus(VertexCollection& vertices, IndexCollection& indices, float diameter, float thickness, size_t tessellation, bool rhcoords); + void ComputeTetrahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeOctahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeDodecahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeIcosahedron(VertexCollection& vertices, IndexCollection& indices, float size, bool rhcoords); + void ComputeTeapot(VertexCollection& vertices, IndexCollection& indices, float size, size_t tessellation, bool rhcoords); +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/GraphicsMemory.cpp b/Kits/DirectXTK12/Src/GraphicsMemory.cpp new file mode 100644 index 00000000..108f0a93 --- /dev/null +++ b/Kits/DirectXTK12/Src/GraphicsMemory.cpp @@ -0,0 +1,365 @@ +//-------------------------------------------------------------------------------------- +// File: GraphicsMemory.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "GraphicsMemory.h" +#include "PlatformHelpers.h" +#include "LinearAllocator.h" + +#include + +using namespace DirectX; +using Microsoft::WRL::ComPtr; +using ScopedLock = std::lock_guard; + +namespace +{ + static const size_t MinPageSize = 64 * 1024; + static const size_t MinAllocSize = 4 * 1024; + static const size_t AllocatorIndexShift = 12; // start block sizes at 4KB + static const size_t AllocatorPoolCount = 21; // allocation sizes up to 2GB supported + static const size_t PoolIndexScale = 1; // multiply the allocation size this amount to push large values into the next bucket + + static_assert((1 << AllocatorIndexShift) == MinAllocSize, "1 << AllocatorIndexShift must == MinPageSize (in KiB)"); + static_assert((MinPageSize & (MinPageSize - 1)) == 0, "MinPageSize size must be a power of 2"); + static_assert((MinAllocSize & (MinAllocSize - 1)) == 0, "MinAllocSize size must be a power of 2"); + static_assert(MinAllocSize >= (4 * 1024), "MinAllocSize size must be greater than 4K"); + + inline constexpr bool WordSize64() + { + return sizeof(size_t) == 8; + } + + inline size_t NextPow2(size_t x) + { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; +#ifdef _WIN64 + x |= x >> 32; +#endif + return ++x; + } + + inline size_t GetPoolIndexFromSize(size_t x) + { + size_t allocatorPageSize = x >> AllocatorIndexShift; + // gives a value from range: + // 0 - sub-4k allocator + // 1 - 4k allocator + // 2 - 8k allocator + // 4 - 16k allocator + // etc... + // Need to convert to an index. + DWORD bitIndex = 0; +#ifdef _WIN64 + return _BitScanForward64(&bitIndex, allocatorPageSize) ? bitIndex + 1 : 0; +#else + return _BitScanForward(&bitIndex, (DWORD)allocatorPageSize) ? bitIndex + 1 : 0; +#endif + } + + inline size_t GetPageSizeFromPoolIndex(size_t x) + { + x = (x == 0) ? 0 : x - 1; // clamp to zero + return std::max(MinPageSize, size_t(1) << (x + AllocatorIndexShift)); + } + + //-------------------------------------------------------------------------------------- + // DeviceAllocator : honors memory requests associated with a particular device + //-------------------------------------------------------------------------------------- + class DeviceAllocator + { + public: + DeviceAllocator(_In_ ComPtr device) + : mDevice(device) + { + for (size_t i = 0; i < mPools.size(); ++i) + { + size_t pageSize = GetPageSizeFromPoolIndex(i); + mPools[i] = std::make_unique( + mDevice.Get(), + pageSize); + } + } + + GraphicsResource Alloc(_In_ size_t size, _In_ size_t alignment) + { + ScopedLock lock(mMutex); + + // Which memory pool does it live in? + size_t poolSize = NextPow2((alignment + size) * PoolIndexScale); + size_t poolIndex = GetPoolIndexFromSize(poolSize); + assert(poolIndex < mPools.size()); + + // If the allocator isn't initialized yet, do so now + auto& allocator = mPools[poolIndex]; + assert(allocator != nullptr); + assert(poolSize < MinPageSize || poolSize == allocator->PageSize()); + + LinearAllocatorPage* page = allocator->FindPageForAlloc(size, alignment); + if (page == nullptr) + throw std::exception("Out of memory"); + + size_t offset = page->Suballocate(size, alignment); + + // Return the information to the user + return std::move(GraphicsResource( + page, + page->GpuAddress() + offset, + page->UploadResource(), + reinterpret_cast(page->BaseMemory()) + offset, + offset, + size)); + } + + // Submit page fences to the command queue + void KickFences(_In_ ID3D12CommandQueue* commandQueue) + { + ScopedLock lock(mMutex); + + for (auto& i : mPools) + { + if (i != nullptr) + { + i->RetirePendingPages(); + i->FenceCommittedPages(commandQueue); + } + } + } + + void GarbageCollect() + { + ScopedLock lock(mMutex); + + for (auto& i : mPools) + { + if (i != nullptr) + { + i->Shrink(); + } + } + } + + private: + ComPtr mDevice; + std::array, AllocatorPoolCount> mPools; + std::mutex mMutex; + }; +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +// GraphicsMemory::Impl +//-------------------------------------------------------------------------------------- + +class GraphicsMemory::Impl +{ +public: + Impl(GraphicsMemory* owner) + : mOwner(owner) + { + if (s_graphicsMemory) + { + throw std::exception("GraphicsMemory is a singleton"); + } + + s_graphicsMemory = this; + } + + ~Impl() + { + mDeviceAllocator.reset(); + s_graphicsMemory = nullptr; + } + + void Initialize(_In_ ID3D12Device* device) + { + mDeviceAllocator = std::make_unique(device); + } + + GraphicsResource Allocate(size_t size, size_t alignment) + { + return std::move(mDeviceAllocator->Alloc(size, alignment)); + } + + void Commit(_In_ ID3D12CommandQueue* commandQueue) + { + mDeviceAllocator->KickFences(commandQueue); + } + + void GarbageCollect() + { + mDeviceAllocator->GarbageCollect(); + } + + GraphicsMemory* mOwner; + static GraphicsMemory::Impl* s_graphicsMemory; + +private: + std::unique_ptr mDeviceAllocator; +}; + +GraphicsMemory::Impl* GraphicsMemory::Impl::s_graphicsMemory = nullptr; + + +//-------------------------------------------------------------------------------------- +// GraphicsMemory +//-------------------------------------------------------------------------------------- + +// Public constructor. +GraphicsMemory::GraphicsMemory(_In_ ID3D12Device* device) + : pImpl(new Impl(this)) +{ + pImpl->Initialize(device); +} + + +// Move constructor. +GraphicsMemory::GraphicsMemory(GraphicsMemory&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ + pImpl->mOwner = this; +} + + +// Move assignment. +GraphicsMemory& GraphicsMemory::operator= (GraphicsMemory&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + pImpl->mOwner = this; + return *this; +} + + +// Public destructor. +GraphicsMemory::~GraphicsMemory() +{ +} + +GraphicsResource GraphicsMemory::Allocate(size_t size, size_t alignment) +{ + return std::move(pImpl->Allocate(size, alignment)); +} + + +void GraphicsMemory::Commit(_In_ ID3D12CommandQueue* commandQueue) +{ + pImpl->Commit(commandQueue); +} + +void GraphicsMemory::GarbageCollect() +{ + pImpl->GarbageCollect(); +} + + +GraphicsMemory& GraphicsMemory::Get() +{ + if (!Impl::s_graphicsMemory || !Impl::s_graphicsMemory->mOwner) + throw std::exception("GraphicsMemory singleton not created"); + + return *Impl::s_graphicsMemory->mOwner; +} + + +//-------------------------------------------------------------------------------------- +// GraphicsResource smart-pointer interface +//-------------------------------------------------------------------------------------- + +GraphicsResource::GraphicsResource() + : mPage(nullptr) + , mGpuAddress {} + , mResource(nullptr) + , mMemory(nullptr) + , mBufferOffset(0) + , mSize(0) +{ +} + +GraphicsResource::GraphicsResource( + _In_ LinearAllocatorPage* page, + _In_ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress, + _In_ ID3D12Resource* resource, + _In_ void* memory, + _In_ size_t offset, + _In_ size_t size) + : mPage(page) + , mGpuAddress(gpuAddress) + , mResource(resource) + , mMemory(memory) + , mBufferOffset(offset) + , mSize(size) +{ + mPage->AddRef(); +} + +GraphicsResource::GraphicsResource(GraphicsResource&& other) + : mPage(nullptr) +{ + Reset(std::move(other)); +} + +GraphicsResource::~GraphicsResource() +{ + if (mPage != nullptr) + { + mPage->Release(); + } +} + +GraphicsResource&& GraphicsResource::operator= (GraphicsResource&& other) +{ + Reset(std::move(other)); + return std::move(*this); +} + +void GraphicsResource::Reset() +{ + if (mPage != nullptr) + { + mPage->Release(); + } + + mPage = nullptr; + mGpuAddress = {}; + mResource = nullptr; + mMemory = nullptr; + mBufferOffset = 0; + mSize = 0; +} + +void GraphicsResource::Reset(GraphicsResource&& alloc) +{ + if (mPage != nullptr) + { + mPage->Release(); + } + + mGpuAddress = alloc.GpuAddress(); + mResource = alloc.Resource(); + mMemory = alloc.Memory(); + mBufferOffset = alloc.ResourceOffset(); + mSize = alloc.Size(); + mPage = alloc.mPage; + + alloc.mGpuAddress = {}; + alloc.mResource = nullptr; + alloc.mMemory = nullptr; + alloc.mBufferOffset = 0; + alloc.mSize = 0; + alloc.mPage = nullptr; +} diff --git a/Kits/DirectXTK12/Src/Keyboard.cpp b/Kits/DirectXTK12/Src/Keyboard.cpp new file mode 100644 index 00000000..d42f9def --- /dev/null +++ b/Kits/DirectXTK12/Src/Keyboard.cpp @@ -0,0 +1,520 @@ +//-------------------------------------------------------------------------------------- +// File: Keyboard.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Keyboard.h" + +#include "PlatformHelpers.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +static_assert(sizeof(Keyboard::State) == (256 / 8), "Size mismatch for State"); + +namespace +{ + void KeyDown(int key, Keyboard::State& state) + { + if (key < 0 || key > 0xfe) + return; + + auto ptr = reinterpret_cast(&state); + + unsigned int bf = 1u << (key & 0x1f); + ptr[(key >> 5)] |= bf; + } + + void KeyUp(int key, Keyboard::State& state) + { + if (key < 0 || key > 0xfe) + return; + + auto ptr = reinterpret_cast(&state); + + unsigned int bf = 1u << (key & 0x1f); + ptr[(key >> 5)] &= ~bf; + } +} + + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) + +//====================================================================================== +// Windows Store or Universal Windows Platform (UWP) app implementation +//====================================================================================== + +// +// For a Windows Store app or Universal Windows Platform (UWP) app, add the following: +// +// void App::SetWindow(CoreWindow^ window ) +// { +// m_keyboard->SetWindow(window); +// } +// + +class Keyboard::Impl +{ +public: + Impl(Keyboard* owner) : + mOwner(owner) + { + mAcceleratorKeyToken.value = 0; + mActivatedToken.value = 0; + + if ( s_keyboard ) + { + throw std::exception( "Keyboard is a singleton" ); + } + + s_keyboard = this; + + memset( &mState, 0, sizeof(State) ); + } + + ~Impl() + { + s_keyboard = nullptr; + + RemoveHandlers(); + } + + void GetState(State& state) const + { + memcpy( &state, &mState, sizeof(State) ); + } + + void Reset() + { + memset( &mState, 0, sizeof(State) ); + } + + void SetWindow(ABI::Windows::UI::Core::ICoreWindow* window) + { + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::UI::Core; + + if (mWindow.Get() == window) + return; + + RemoveHandlers(); + + mWindow = window; + + if (!window) + return; + + typedef __FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs ActivatedHandler; + HRESULT hr = window->add_Activated(Callback(Activated).Get(), &mActivatedToken); + ThrowIfFailed(hr); + + ComPtr dispatcher; + hr = window->get_Dispatcher( dispatcher.GetAddressOf() ); + ThrowIfFailed(hr); + + ComPtr keys; + hr = dispatcher.As(&keys); + ThrowIfFailed(hr); + + typedef __FITypedEventHandler_2_Windows__CUI__CCore__CCoreDispatcher_Windows__CUI__CCore__CAcceleratorKeyEventArgs AcceleratorKeyHandler; + hr = keys->add_AcceleratorKeyActivated( Callback(AcceleratorKeyEvent).Get(), &mAcceleratorKeyToken); + ThrowIfFailed(hr); + } + + State mState; + Keyboard* mOwner; + + static Keyboard::Impl* s_keyboard; + +private: + ComPtr mWindow; + + EventRegistrationToken mAcceleratorKeyToken; + EventRegistrationToken mActivatedToken; + + void RemoveHandlers() + { + if (mWindow) + { + using namespace ABI::Windows::UI::Core; + + ComPtr dispatcher; + HRESULT hr = mWindow->get_Dispatcher( dispatcher.GetAddressOf() ); + ThrowIfFailed(hr); + + mWindow->remove_Activated(mActivatedToken); + mActivatedToken.value = 0; + + ComPtr keys; + hr = dispatcher.As(&keys); + ThrowIfFailed(hr); + + keys->remove_AcceleratorKeyActivated(mAcceleratorKeyToken); + mAcceleratorKeyToken.value = 0; + } + } + + static HRESULT Activated( IInspectable *, ABI::Windows::UI::Core::IWindowActivatedEventArgs* ) + { + auto pImpl = Impl::s_keyboard; + + if (!pImpl) + return S_OK; + + pImpl->Reset(); + + return S_OK; + } + + static HRESULT AcceleratorKeyEvent( IInspectable *, ABI::Windows::UI::Core::IAcceleratorKeyEventArgs* args ) + { + using namespace ABI::Windows::System; + using namespace ABI::Windows::UI::Core; + + auto pImpl = Impl::s_keyboard; + + if (!pImpl) + return S_OK; + + CoreAcceleratorKeyEventType evtType; + HRESULT hr = args->get_EventType(&evtType); + ThrowIfFailed(hr); + + bool down = false; + + switch (evtType) + { + case CoreAcceleratorKeyEventType_KeyDown: + case CoreAcceleratorKeyEventType_SystemKeyDown: + down = true; + break; + + case CoreAcceleratorKeyEventType_KeyUp: + case CoreAcceleratorKeyEventType_SystemKeyUp: + break; + + default: + return S_OK; + } + + CorePhysicalKeyStatus status; + hr = args->get_KeyStatus(&status); + ThrowIfFailed(hr); + + VirtualKey virtualKey; + hr = args->get_VirtualKey(&virtualKey); + ThrowIfFailed(hr); + + int vk = static_cast( virtualKey ); + + switch (vk) + { + case VK_SHIFT: + vk = (status.ScanCode == 0x36) ? VK_RSHIFT : VK_LSHIFT; + if ( !down ) + { + // Workaround to ensure left vs. right shift get cleared when both were pressed at same time + KeyUp(VK_LSHIFT, pImpl->mState); + KeyUp(VK_RSHIFT, pImpl->mState); + } + break; + + case VK_CONTROL: + vk = (status.IsExtendedKey) ? VK_RCONTROL : VK_LCONTROL; + break; + + case VK_MENU: + vk = (status.IsExtendedKey) ? VK_RMENU : VK_LMENU; + break; + } + + if (down) + { + KeyDown(vk, pImpl->mState); + } + else + { + KeyUp(vk, pImpl->mState); + } + + return S_OK; + } +}; + + +Keyboard::Impl* Keyboard::Impl::s_keyboard = nullptr; + + +void Keyboard::SetWindow(ABI::Windows::UI::Core::ICoreWindow* window) +{ + pImpl->SetWindow(window); +} + +#elif defined(_XBOX_ONE) || ( defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ) + +//====================================================================================== +// Null device for Windows Phone and Xbox One +//====================================================================================== + +class Keyboard::Impl +{ +public: + Impl(Keyboard* owner) : + mOwner(owner) + { + if ( s_keyboard ) + { + throw std::exception( "Keyboard is a singleton" ); + } + + s_keyboard = this; + } + + ~Impl() + { + s_keyboard = nullptr; + } + + void GetState(State& state) const + { + memset( &state, 0, sizeof(State) ); + } + + void Reset() + { + } + + Keyboard* mOwner; + + static Keyboard::Impl* s_keyboard; +}; + +Keyboard::Impl* Keyboard::Impl::s_keyboard = nullptr; + +#else + +//====================================================================================== +// Win32 desktop implementation +//====================================================================================== + +// +// For a Win32 desktop application, call this function from your Window Message Procedure +// +// LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +// { +// switch (message) +// { +// +// case WM_ACTIVATEAPP: +// Keyboard::ProcessMessage(message, wParam, lParam); +// break; +// +// case WM_KEYDOWN: +// case WM_SYSKEYDOWN: +// case WM_KEYUP: +// case WM_SYSKEYUP: +// Keyboard::ProcessMessage(message, wParam, lParam); +// break; +// +// } +// } +// + +class Keyboard::Impl +{ +public: + Impl(Keyboard* owner) : + mOwner(owner) + { + if ( s_keyboard ) + { + throw std::exception( "Keyboard is a singleton" ); + } + + s_keyboard = this; + + memset( &mState, 0, sizeof(State) ); + } + + ~Impl() + { + s_keyboard = nullptr; + } + + void GetState(State& state) const + { + memcpy( &state, &mState, sizeof(State) ); + } + + void Reset() + { + memset( &mState, 0, sizeof(State) ); + } + + State mState; + Keyboard* mOwner; + + static Keyboard::Impl* s_keyboard; +}; + + +Keyboard::Impl* Keyboard::Impl::s_keyboard = nullptr; + + +void Keyboard::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + auto pImpl = Impl::s_keyboard; + + if (!pImpl) + return; + + bool down = false; + + switch (message) + { + case WM_ACTIVATEAPP: + pImpl->Reset(); + return; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + down = true; + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + break; + + default: + return; + } + + int vk = static_cast( wParam ); + switch (vk) + { + case VK_SHIFT: + vk = MapVirtualKey((lParam & 0x00ff0000) >> 16, MAPVK_VSC_TO_VK_EX); + if ( !down ) + { + // Workaround to ensure left vs. right shift get cleared when both were pressed at same time + KeyUp(VK_LSHIFT, pImpl->mState); + KeyUp(VK_RSHIFT, pImpl->mState); + } + break; + + case VK_CONTROL: + vk = (lParam & 0x01000000) ? VK_RCONTROL : VK_LCONTROL; + break; + + case VK_MENU: + vk = (lParam & 0x01000000) ? VK_RMENU : VK_LMENU; + break; + } + + if (down) + { + KeyDown(vk, pImpl->mState); + } + else + { + KeyUp(vk, pImpl->mState); + } +} + +#endif + +#pragma warning( disable : 4355 ) + +// Public constructor. +Keyboard::Keyboard() + : pImpl( new Impl(this) ) +{ +} + + +// Move constructor. +Keyboard::Keyboard(Keyboard&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ + pImpl->mOwner = this; +} + + +// Move assignment. +Keyboard& Keyboard::operator= (Keyboard&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + pImpl->mOwner = this; + return *this; +} + + +// Public destructor. +Keyboard::~Keyboard() +{ +} + + +Keyboard::State Keyboard::GetState() const +{ + State state; + pImpl->GetState(state); + return state; +} + + +void Keyboard::Reset() +{ + pImpl->Reset(); +} + + +Keyboard& Keyboard::Get() +{ + if ( !Impl::s_keyboard || !Impl::s_keyboard->mOwner ) + throw std::exception( "Keyboard is a singleton" ); + + return *Impl::s_keyboard->mOwner; +} + + + +//====================================================================================== +// KeyboardStateTracker +//====================================================================================== + +void Keyboard::KeyboardStateTracker::Update( const State& state ) +{ + auto currPtr = reinterpret_cast(&state); + auto prevPtr = reinterpret_cast(&lastState); + auto releasedPtr = reinterpret_cast(&released); + auto pressedPtr = reinterpret_cast(&pressed); + for (size_t j = 0; j < (256 / 32); ++j) + { + *pressedPtr = *currPtr & ~(*prevPtr); + *releasedPtr = ~(*currPtr) & *prevPtr; + + ++currPtr; + ++prevPtr; + ++releasedPtr; + ++pressedPtr; + } + + lastState = state; +} + + +void Keyboard::KeyboardStateTracker::Reset() +{ + memset( this, 0, sizeof(KeyboardStateTracker) ); +} diff --git a/Kits/DirectXTK12/Src/LinearAllocator.cpp b/Kits/DirectXTK12/Src/LinearAllocator.cpp new file mode 100644 index 00000000..9ecc843a --- /dev/null +++ b/Kits/DirectXTK12/Src/LinearAllocator.cpp @@ -0,0 +1,498 @@ +//-------------------------------------------------------------------------------------- +// File: LinearAllocator.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "LinearAllocator.h" + +#define VALIDATE_LISTS 0 + +#if VALIDATE_LISTS +# include +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + inline size_t AlignOffset(size_t offset, size_t alignment) + { + if (alignment > 0) + { + // Alignment must be a power of 2 + assert((alignment & (alignment - 1)) == 0); + offset = (offset + alignment - 1) & ~(alignment - 1); + } + return offset; + } +} + +LinearAllocatorPage::LinearAllocatorPage() + : pPrevPage(nullptr) + , pNextPage(nullptr) + , mMemory(nullptr) + , mUploadResource(nullptr) + , mFence(nullptr) + , mPendingFence(0) + , mGpuAddress {} + , mOffset(0) + , mSize(0) + , mRefCount(0) +{ +} + +size_t LinearAllocatorPage::Suballocate(_In_ size_t size, _In_ size_t alignment) +{ + size_t offset = AlignOffset(mOffset, alignment); +#ifdef _DEBUG + if (offset + size > mSize) + throw std::exception("Out of free memory in page suballoc"); +#endif + mOffset = offset + size; + return offset; +} + +LinearAllocator::LinearAllocator( + _In_ ID3D12Device* pDevice, + _In_ size_t pageSize, + _In_ size_t preallocateBytes) + : m_pendingPages( nullptr ) + , m_usedPages( nullptr ) + , m_unusedPages( nullptr ) + , m_increment( 0 ) +{ + m_increment = pageSize; + m_usedPages = nullptr; + m_unusedPages = nullptr; + m_pendingPages = nullptr; + m_device = pDevice; + m_totalPages = 0; + m_numPending = 0; + + size_t preallocatePageCount = ( ( preallocateBytes + pageSize - 1 ) / pageSize ); + for (size_t preallocatePages = 0; preallocateBytes != 0 && preallocatePages < preallocatePageCount; ++preallocatePages ) + { + if ( GetNewPage() == nullptr ) + { + throw std::exception("Out of memory."); + } + } +} + +LinearAllocator::~LinearAllocator() +{ + // Must wait for all pending fences! + while ( m_pendingPages != nullptr ) + { + RetirePendingPages(); + } + + assert( m_pendingPages == nullptr ); + + // Return all the memory + FreePages( m_unusedPages ); + FreePages( m_usedPages ); + + m_pendingPages = nullptr; + m_usedPages = nullptr; + m_unusedPages = nullptr; + m_increment = 0; +} + +LinearAllocatorPage* LinearAllocator::FindPageForAlloc(_In_ size_t size, _In_ size_t alignment) +{ +#ifdef _DEBUG + if( size > m_increment ) + throw std::out_of_range(__FUNCTION__ " size must be less or equal to the allocator's increment"); + if( alignment > m_increment ) + throw std::out_of_range(__FUNCTION__ " alignment must be less or equal to the allocator's increment"); + if ( size == 0 ) + throw std::exception("Cannot honor zero size allocation request."); +#endif + + LinearAllocatorPage* page = GetPageForAlloc( size, alignment ); + if ( page == nullptr ) + { + throw std::exception("Out of memory."); + } + + return page; +} + +// Call this after you submit your work to the driver. +void LinearAllocator::FenceCommittedPages(_In_ ID3D12CommandQueue* commandQueue) +{ + // No pending pages + if (m_usedPages == nullptr) + return; + + // For all the used pages, fence them + UINT numReady = 0; + LinearAllocatorPage* readyPages = nullptr; + LinearAllocatorPage* unreadyPages = nullptr; + LinearAllocatorPage* nextPage = nullptr; + for (LinearAllocatorPage* page = m_usedPages; page != nullptr; page = nextPage) + { + nextPage = page->pNextPage; + + // Disconnect from the list + page->pPrevPage = nullptr; + + if (page->RefCount() == 0) + { + // Signal the fence + numReady++; + commandQueue->Signal(page->mFence.Get(), ++page->mPendingFence); + + // Link to the ready pages list + page->pNextPage = readyPages; + if (readyPages) readyPages->pPrevPage = page; + readyPages = page; + } + else + { + // Link to the unready list + page->pNextPage = unreadyPages; + if (unreadyPages) unreadyPages->pPrevPage = page; + unreadyPages = page; + } + } + + // Replace the used pages list with the new unready list + m_usedPages = unreadyPages; + + // Append all those pages from the ready list to the pending list + if (numReady > 0) + { + m_numPending += numReady; + LinkPageChain(readyPages, m_pendingPages); + } + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +// Call this once a frame after all of your driver submissions. +// (immediately before or after Present-time) +void LinearAllocator::RetirePendingPages() +{ + // For each page that we know has a fence pending, check it. If the fence has passed, + // we can mark the page for re-use. + LinearAllocatorPage* page = m_pendingPages; + while ( page != nullptr ) + { + LinearAllocatorPage* nextPage = page->pNextPage; + + assert( page->mPendingFence != 0 ); + + if ( page->mFence->GetCompletedValue() >= page->mPendingFence ) + { + // Fence has passed. It is safe to use this page again. + ReleasePage( page ); + } + + page = nextPage; + } +} + +void LinearAllocator::Shrink() +{ + FreePages( m_unusedPages ); + m_unusedPages = nullptr; + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +LinearAllocatorPage* LinearAllocator::GetCleanPageForAlloc() +{ + // Grab the first unused page, if one exists. Else, allocate a new page. + LinearAllocatorPage* page = m_unusedPages; + if (page == nullptr) + { + // Allocate a new page + page = GetNewPage(); + if (page == nullptr) + { + // OOM. + return nullptr; + } + } + + // Mark this page as used + UnlinkPage(page); + LinkPage(page, m_usedPages); + + assert(page->mOffset == 0); + + return page; +} + +LinearAllocatorPage* LinearAllocator::GetPageForAlloc( + size_t sizeBytes, + size_t alignment) +{ + // Fast path + if ( sizeBytes == m_increment && (alignment == 0 || alignment == m_increment) ) + { + return GetCleanPageForAlloc(); + } + + // Find a page in the pending pages list that has space. + LinearAllocatorPage* page = FindPageForAlloc( m_usedPages, sizeBytes, alignment ); + if ( page == nullptr ) + { + page = GetCleanPageForAlloc(); + } + + return page; +} + +LinearAllocatorPage* LinearAllocator::FindPageForAlloc( + LinearAllocatorPage* list, + size_t sizeBytes, + size_t alignment) +{ + for ( LinearAllocatorPage* page = list; page != nullptr; page = page->pNextPage ) + { + size_t offset = AlignOffset(page->mOffset, alignment); + if ( offset + sizeBytes <= m_increment ) + return page; + } + return nullptr; +} + +LinearAllocatorPage* LinearAllocator::GetNewPage() +{ + ComPtr spResource; + + CD3DX12_HEAP_PROPERTIES uploadHeapProperties( D3D12_HEAP_TYPE_UPLOAD ); + CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer( m_increment ); + + // Allocate the upload heap + if (FAILED(m_device->CreateCommittedResource( + &uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_GRAPHICS_PPV_ARGS(spResource.ReleaseAndGetAddressOf()) ))) + { + return nullptr; + } + + if (m_debugName.size() > 0) + { + spResource->SetName(m_debugName.c_str()); + } + + // Get a pointer to the memory + void* pMemory = nullptr; + ThrowIfFailed(spResource->Map( 0, nullptr, &pMemory )); + memset(pMemory, 0, m_increment); + + // Create a fence + ComPtr spFence; + if (FAILED(m_device->CreateFence( + 0, + D3D12_FENCE_FLAG_NONE, + IID_GRAPHICS_PPV_ARGS(spFence.ReleaseAndGetAddressOf()) ))) + { + return nullptr; + } + + // Add the page to the page list + LinearAllocatorPage* page = new LinearAllocatorPage; + page->mSize = m_increment; + page->mMemory = pMemory; + page->pPrevPage = nullptr; + page->pNextPage = m_unusedPages; + page->mUploadResource = spResource; + page->mFence = spFence; + page->mGpuAddress = spResource->GetGPUVirtualAddress(); + + // Set as head of the list + page->pNextPage = m_unusedPages; + if (m_unusedPages) m_unusedPages->pPrevPage = page; + m_unusedPages = page; + m_totalPages++; + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif + + return page; +} + +void LinearAllocator::UnlinkPage( LinearAllocatorPage* page ) +{ + if ( page->pPrevPage ) + page->pPrevPage->pNextPage = page->pNextPage; + + // Check that it isn't the head of any of our tracked lists + else if ( page == m_unusedPages ) + m_unusedPages = page->pNextPage; + else if ( page == m_usedPages ) + m_usedPages = page->pNextPage; + else if ( page == m_pendingPages ) + m_pendingPages = page->pNextPage; + + if ( page->pNextPage ) + page->pNextPage->pPrevPage = page->pPrevPage; + + page->pNextPage = nullptr; + page->pPrevPage = nullptr; + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +void LinearAllocator::LinkPageChain(LinearAllocatorPage* page, LinearAllocatorPage*& list) +{ +#if VALIDATE_LISTS + // Walk the chain and ensure it's not in the list twice + for (LinearAllocatorPage* cur = list; cur != nullptr; cur = cur->pNextPage) + { + assert(cur != page); + } +#endif + assert(page->pPrevPage == nullptr); + assert(list == nullptr || list->pPrevPage == nullptr); + + // Follow chain to the end and append + LinearAllocatorPage* lastPage = nullptr; + for (lastPage = page; lastPage->pNextPage != nullptr; lastPage = lastPage->pNextPage) {} + + lastPage->pNextPage = list; + if (list) + list->pPrevPage = lastPage; + + list = page; + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +void LinearAllocator::LinkPage( LinearAllocatorPage* page, LinearAllocatorPage*& list ) +{ +#if VALIDATE_LISTS + // Walk the chain and ensure it's not in the list twice + for ( LinearAllocatorPage* cur = list; cur != nullptr; cur = cur->pNextPage ) + { + assert( cur != page ); + } +#endif + assert(page->pNextPage == nullptr); + assert(page->pPrevPage == nullptr); + assert(list == nullptr || list->pPrevPage == nullptr); + + page->pNextPage = list; + if ( list ) + list->pPrevPage = page; + + list = page; + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +void LinearAllocator::ReleasePage( LinearAllocatorPage* page ) +{ + assert( m_numPending > 0 ); + m_numPending--; + + UnlinkPage( page ); + LinkPage( page, m_unusedPages ); + + // Reset the page offset (effectively erasing the memory) + page->mOffset = 0; + +#ifdef _DEBUG + memset( page->mMemory, 0, m_increment ); +#endif + +#if VALIDATE_LISTS + ValidatePageLists(); +#endif +} + +void LinearAllocator::FreePages( LinearAllocatorPage* page ) +{ + while ( page != nullptr ) + { + LinearAllocatorPage* nextPage = page->pNextPage; + + page->mUploadResource->Unmap( 0, nullptr ); + delete page; + + page = nextPage; + m_totalPages--; + } +} + +#if VALIDATE_LISTS +void LinearAllocator::ValidateList(LinearAllocatorPage* list) +{ + for (LinearAllocatorPage* page = list, *lastPage = nullptr; + page != nullptr; + lastPage = page, page = page->pNextPage) + { + if (page->pPrevPage != lastPage) + { + throw std::exception("Broken link to previous"); + } + } +} + +void LinearAllocator::ValidatePageLists() +{ + ValidateList(m_pendingPages); + ValidateList(m_usedPages); + ValidateList(m_unusedPages); +} +#endif + +void LinearAllocator::SetDebugName(const char* name) +{ + wchar_t wname[MAX_PATH] = {}; + int result = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, (int) strlen(name), wname, MAX_PATH); + if ( result > 0 ) + { + SetDebugName(wname); + } +} + +void LinearAllocator::SetDebugName(const wchar_t* name) +{ + m_debugName = name; + + // Rename existing pages + SetPageDebugName(m_pendingPages); + SetPageDebugName(m_usedPages); + SetPageDebugName(m_unusedPages); +} + +void LinearAllocator::SetPageDebugName(LinearAllocatorPage* list) +{ + for ( LinearAllocatorPage* page = list; page != nullptr; page = page->pNextPage ) + { + page->mUploadResource->SetName(m_debugName.c_str()); + } +} diff --git a/Kits/DirectXTK12/Src/LinearAllocator.h b/Kits/DirectXTK12/Src/LinearAllocator.h new file mode 100644 index 00000000..6c638864 --- /dev/null +++ b/Kits/DirectXTK12/Src/LinearAllocator.h @@ -0,0 +1,161 @@ +//-------------------------------------------------------------------------------------- +// LinearAllocator.h +// +// A linear allocator. When Allocate is called it will try to return you a pointer into +// existing graphics memory. If there is no space left from what is allocated, more +// pages are allocated on-the-fly. +// +// Each allocation must be smaller or equal to pageSize. It is not necessary but is most +// efficient for the sizes to be some fraction of pageSize. pageSize does not determine +// the size of the physical pages underneath the virtual memory (that's given by the +// XMemAttributes) but is how much additional memory the allocator should allocate +// each time you run out of space. +// +// preallocatePages specifies how many pages to initially allocate. Specifying zero will +// preallocate two pages by default. +// +// This class is NOT thread safe. You should protect this with the appropriate sync +// primitives or, even better, use one linear allocator per thread. +// +// Pages are freed once the GPU is done with them. As such, you need to specify when a +// page is in use and when it is no longer in use. Use RetirePages to prompt the +// allocator to check if pages are no longer being used by the GPU. Use InsertFences to +// mark all used pages as in-use by the GPU, removing them from the available pages +// list. It is recommended you call RetirePages and InsertFences once a frame, usually +// just before Present(). +// +// Why is RetirePages decoupled from InsertFences? It's possible that you might want to +// reclaim pages more frequently than locking used pages. For example, if you find the +// allocator is burning through pages too quickly you can call RetirePages to reclaim +// some that the GPU has finished with. However, this adds additional CPU overhead so it +// is left to you to decide. In most cases this is sufficient: +// +// allocator.RetirePages(); +// allocator.InsertFences( pContext, 0 ); +// DXGIXPresentArray(...); +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include + + +namespace DirectX +{ + class LinearAllocatorPage + { + public: + LinearAllocatorPage(); + + size_t Suballocate(_In_ size_t size, _In_ size_t alignment); + + void* BaseMemory() const { return mMemory; } + ID3D12Resource* UploadResource() const { return mUploadResource.Get(); } + D3D12_GPU_VIRTUAL_ADDRESS GpuAddress() const { return mGpuAddress; } + size_t BytesUsed() const { return mOffset; } + size_t Size() const { return mSize; } + + int32_t AddRef() { return mRefCount.fetch_add(1); } + int32_t Release() { assert(mRefCount > 0); return mRefCount.fetch_sub(1); } + int32_t RefCount() const { return mRefCount.load(); } + + protected: + friend class LinearAllocator; + + LinearAllocatorPage* pPrevPage; + LinearAllocatorPage* pNextPage; + + void* mMemory; + Microsoft::WRL::ComPtr mUploadResource; + Microsoft::WRL::ComPtr mFence; + uint64_t mPendingFence; + D3D12_GPU_VIRTUAL_ADDRESS mGpuAddress; + size_t mOffset; + size_t mSize; + + private: + std::atomic mRefCount; + }; + + class LinearAllocator + { + public: + // These values will be rounded up to the nearest 64k. + // You can specify zero for incrementalSizeBytes to increment + // by 1 page (64k). + LinearAllocator( + _In_ ID3D12Device* pDevice, + _In_ size_t pageSize, + _In_ size_t preallocateBytes = 0); + + LinearAllocator(const LinearAllocator& m) = delete; + LinearAllocator& operator = (const LinearAllocator& m) = delete; + + ~LinearAllocator(); + + // Allow move semantics on this object. + LinearAllocator(LinearAllocator&& m) = default; + + LinearAllocatorPage* FindPageForAlloc(_In_ size_t requestedSize, _In_ size_t alignment); + + // Call this at least once a frame to check if pages have become available. + void RetirePendingPages(); + + // Call this after you submit your work to the driver. + // (e.g. immediately before Present.) + void FenceCommittedPages(_In_ ID3D12CommandQueue* commandQueue); + + // Throws away all currently unused pages + void Shrink(); + + // Statistics + size_t CommittedPageCount() const { return m_numPending; } + size_t TotalPageCount() const { return m_totalPages; } + size_t CommittedMemoryUsage() const { return m_numPending * m_increment; } + size_t TotalMemoryUsage() const { return m_totalPages * m_increment; } + size_t PageSize() const { return m_increment; } + + // Debug info + const wchar_t* GetDebugName() const { return m_debugName.c_str(); } + void SetDebugName(const wchar_t* name); + void SetDebugName(const char* name); + + private: + std::wstring m_debugName; + Microsoft::WRL::ComPtr m_device; + LinearAllocatorPage* m_pendingPages; // Pages in use by the GPU + LinearAllocatorPage* m_usedPages; // Pages to be submitted to the GPU + LinearAllocatorPage* m_unusedPages; // Pages not being used right now + size_t m_increment; + size_t m_numPending; + size_t m_totalPages; + + LinearAllocatorPage* GetPageForAlloc(size_t sizeBytes, size_t alignment); + LinearAllocatorPage* GetCleanPageForAlloc(); + + LinearAllocatorPage* FindPageForAlloc(LinearAllocatorPage* list, size_t sizeBytes, size_t alignment); + + LinearAllocatorPage* GetNewPage(); + + void UnlinkPage(LinearAllocatorPage* page); + void LinkPage(LinearAllocatorPage* page, LinearAllocatorPage*& list); + void LinkPageChain(LinearAllocatorPage* page, LinearAllocatorPage*& list); + void ReleasePage(LinearAllocatorPage* page); + void FreePages(LinearAllocatorPage* list); + + // Debug only + static void ValidateList(LinearAllocatorPage* list); + void ValidatePageLists(); + + void SetPageDebugName(LinearAllocatorPage* list); + }; +} diff --git a/Kits/DirectXTK12/Src/LoaderHelpers.h b/Kits/DirectXTK12/Src/LoaderHelpers.h new file mode 100644 index 00000000..c12c0fe7 --- /dev/null +++ b/Kits/DirectXTK12/Src/LoaderHelpers.h @@ -0,0 +1,858 @@ +//-------------------------------------------------------------------------------------- +// File: LoaderHelpers.h +// +// Helper functions for texture loaders and screen grabber +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DDS.h" +#include "DDSTextureLoader.h" + + +namespace DirectX +{ + //-------------------------------------------------------------------------------------- + // Return the BPP for a particular format + //-------------------------------------------------------------------------------------- + inline size_t BitsPerPixel(_In_ DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_YUY2: + return 32; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + return 24; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_NV11: + return 12; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return 32; + + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: + return 24; + + case DXGI_FORMAT_R4G4_UNORM: + return 8; + +#endif // _XBOX_ONE && _TITLE + + default: + return 0; + } + } + + //-------------------------------------------------------------------------------------- + inline DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + + case DXGI_FORMAT_BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return format; + } + } + + //-------------------------------------------------------------------------------------- + inline bool IsCompressed(_In_ DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + + default: + return false; + } + } + + //-------------------------------------------------------------------------------------- + inline DXGI_FORMAT EnsureNotTypeless(DXGI_FORMAT fmt) + { + // Assumes UNORM or FLOAT; doesn't use UINT or SINT + switch (fmt) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_R32G32B32_TYPELESS: return DXGI_FORMAT_R32G32B32_FLOAT; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: return DXGI_FORMAT_R16G16B16A16_UNORM; + case DXGI_FORMAT_R32G32_TYPELESS: return DXGI_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: return DXGI_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_R16G16_TYPELESS: return DXGI_FORMAT_R16G16_UNORM; + case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R8G8_TYPELESS: return DXGI_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_TYPELESS: return DXGI_FORMAT_R16_UNORM; + case DXGI_FORMAT_R8_TYPELESS: return DXGI_FORMAT_R8_UNORM; + case DXGI_FORMAT_BC1_TYPELESS: return DXGI_FORMAT_BC1_UNORM; + case DXGI_FORMAT_BC2_TYPELESS: return DXGI_FORMAT_BC2_UNORM; + case DXGI_FORMAT_BC3_TYPELESS: return DXGI_FORMAT_BC3_UNORM; + case DXGI_FORMAT_BC4_TYPELESS: return DXGI_FORMAT_BC4_UNORM; + case DXGI_FORMAT_BC5_TYPELESS: return DXGI_FORMAT_BC5_UNORM; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: return DXGI_FORMAT_B8G8R8X8_UNORM; + case DXGI_FORMAT_BC7_TYPELESS: return DXGI_FORMAT_BC7_UNORM; + default: return fmt; + } + } + + //-------------------------------------------------------------------------------------- + inline HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t* fileName, + std::unique_ptr& ddsData, + DDS_HEADER** header, + uint8_t** bitData, + size_t* bitSize + ) + { + if (!header || !bitData || !bitSize) + { + return E_POINTER; + } + + // open the file +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile(safe_handle(CreateFile2(fileName, + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr))); +#else + ScopedHandle hFile(safe_handle(CreateFileW(fileName, + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr))); +#endif + + if (!hFile) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // Get the file size + FILE_STANDARD_INFO fileInfo; + if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + // File is too big for 32-bit allocation, so reject read + if (fileInfo.EndOfFile.HighPart > 0) + { + return E_FAIL; + } + + // Need at least enough data to fill the header and magic number to be a valid DDS + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + { + return E_FAIL; + } + + // create enough space for the file data + ddsData.reset(new (std::nothrow) uint8_t[fileInfo.EndOfFile.LowPart]); + if (!ddsData) + { + return E_OUTOFMEMORY; + } + + // read the data in + DWORD BytesRead = 0; + if (!ReadFile(hFile.get(), + ddsData.get(), + fileInfo.EndOfFile.LowPart, + &BytesRead, + nullptr + )) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + if (BytesRead < fileInfo.EndOfFile.LowPart) + { + return E_FAIL; + } + + // DDS files always start with the same magic number ("DDS ") + uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); + if (dwMagicNumber != DDS_MAGIC) + { + return E_FAIL; + } + + auto hdr = reinterpret_cast(ddsData.get() + sizeof(uint32_t)); + + // Verify header to validate DDS file + if (hdr->size != sizeof(DDS_HEADER) || + hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) + { + return E_FAIL; + } + + // Check for DX10 extension + bool bDXT10Header = false; + if ((hdr->ddspf.flags & DDS_FOURCC) && + (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) + { + // Must be long enough for both headers and magic value + if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) + { + return E_FAIL; + } + + bDXT10Header = true; + } + + // setup the pointers in the process request + *header = hdr; + ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0); + *bitData = ddsData.get() + offset; + *bitSize = fileInfo.EndOfFile.LowPart - offset; + + return S_OK; + } + + //-------------------------------------------------------------------------------------- + // Get surface information for a particular format + //-------------------------------------------------------------------------------------- + inline void GetSurfaceInfo(_In_ size_t width, + _In_ size_t height, + _In_ DXGI_FORMAT fmt, + _Out_opt_ size_t* outNumBytes, + _Out_opt_ size_t* outRowBytes, + _Out_opt_ size_t* outNumRows) + { + size_t numBytes = 0; + size_t rowBytes = 0; + size_t numRows = 0; + + bool bc = false; + bool packed = false; + bool planar = false; + size_t bpe = 0; + switch (fmt) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + bc = true; + bpe = 8; + break; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + bc = true; + bpe = 16; + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_YUY2: + packed = true; + bpe = 4; + break; + + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + packed = true; + bpe = 8; + break; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_420_OPAQUE: + planar = true; + bpe = 2; + break; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + planar = true; + bpe = 4; + break; + +#if defined(_XBOX_ONE) && defined(_TITLE) + + case DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X16_TYPELESS_G8_UINT: + planar = true; + bpe = 4; + break; + +#endif + } + + if (bc) + { + size_t numBlocksWide = 0; + if (width > 0) + { + numBlocksWide = std::max(1, (width + 3) / 4); + } + size_t numBlocksHigh = 0; + if (height > 0) + { + numBlocksHigh = std::max(1, (height + 3) / 4); + } + rowBytes = numBlocksWide * bpe; + numRows = numBlocksHigh; + numBytes = rowBytes * numBlocksHigh; + } + else if (packed) + { + rowBytes = ((width + 1) >> 1) * bpe; + numRows = height; + numBytes = rowBytes * height; + } + else if (fmt == DXGI_FORMAT_NV11) + { + rowBytes = ((width + 3) >> 2) * 4; + numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data + numBytes = rowBytes * numRows; + } + else if (planar) + { + rowBytes = ((width + 1) >> 1) * bpe; + numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1); + numRows = height + ((height + 1) >> 1); + } + else + { + size_t bpp = BitsPerPixel(fmt); + rowBytes = (width * bpp + 7) / 8; // round up to nearest byte + numRows = height; + numBytes = rowBytes * height; + } + + if (outNumBytes) + { + *outNumBytes = numBytes; + } + if (outRowBytes) + { + *outRowBytes = rowBytes; + } + if (outNumRows) + { + *outNumRows = numRows; + } + } + + //-------------------------------------------------------------------------------------- + #define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a ) + + inline DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT& ddpf) + { + if (ddpf.flags & DDS_RGB) + { + // Note that sRGB formats are written using the "DX10" extended header + + switch (ddpf.RGBBitCount) + { + case 32: + if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + { + return DXGI_FORMAT_R8G8B8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) + { + return DXGI_FORMAT_B8G8R8A8_UNORM; + } + + if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000)) + { + return DXGI_FORMAT_B8G8R8X8_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8 + + // Note that many common DDS reader/writers (including D3DX) swap the + // the RED/BLUE masks for 10:10:10:2 formats. We assume + // below that the 'backwards' header mask is being used since it is most + // likely written by D3DX. The more robust solution is to use the 'DX10' + // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly + + // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data + if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000)) + { + return DXGI_FORMAT_R10G10B10A2_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10 + + if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16G16_UNORM; + } + + if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000)) + { + // Only 32-bit color channel format in D3D9 was R32F + return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 + } + break; + + case 24: + // No 24bpp DXGI formats aka D3DFMT_R8G8B8 + break; + + case 16: + if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000)) + { + return DXGI_FORMAT_B5G5R5A1_UNORM; + } + if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000)) + { + return DXGI_FORMAT_B5G6R5_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5 + + if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000)) + { + return DXGI_FORMAT_B4G4R4A4_UNORM; + } + + // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4 + + // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc. + break; + } + } + else if (ddpf.flags & DDS_LUMINANCE) + { + if (8 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + + // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 + } + + if (16 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension + } + if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) + { + return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension + } + } + } + else if (ddpf.flags & DDS_ALPHA) + { + if (8 == ddpf.RGBBitCount) + { + return DXGI_FORMAT_A8_UNORM; + } + } + else if (ddpf.flags & DDS_BUMPDUDV) + { + if (16 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x00ff, 0xff00, 0x0000, 0x0000)) + { + return DXGI_FORMAT_R8G8_SNORM; // D3DX10/11 writes this out as DX10 extension + } + } + + if (32 == ddpf.RGBBitCount) + { + if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + { + return DXGI_FORMAT_R8G8B8A8_SNORM; // D3DX10/11 writes this out as DX10 extension + } + if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) + { + return DXGI_FORMAT_R16G16_SNORM; // D3DX10/11 writes this out as DX10 extension + } + + // No DXGI format maps to ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) aka D3DFMT_A2W10V10U10 + } + } + else if (ddpf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC1_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + // While pre-multiplied alpha isn't directly supported by the DXGI formats, + // they are basically the same as these BC formats so they can be mapped + if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC2_UNORM; + } + if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC) + { + return DXGI_FORMAT_BC3_UNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_UNORM; + } + if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC4_SNORM; + } + + if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_UNORM; + } + if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC) + { + return DXGI_FORMAT_BC5_SNORM; + } + + // BC6H and BC7 are written using the "DX10" extended header + + if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC) + { + return DXGI_FORMAT_R8G8_B8G8_UNORM; + } + if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC) + { + return DXGI_FORMAT_G8R8_G8B8_UNORM; + } + + if (MAKEFOURCC('Y', 'U', 'Y', '2') == ddpf.fourCC) + { + return DXGI_FORMAT_YUY2; + } + + // Check for D3DFORMAT enums being set here + switch (ddpf.fourCC) + { + case 36: // D3DFMT_A16B16G16R16 + return DXGI_FORMAT_R16G16B16A16_UNORM; + + case 110: // D3DFMT_Q16W16V16U16 + return DXGI_FORMAT_R16G16B16A16_SNORM; + + case 111: // D3DFMT_R16F + return DXGI_FORMAT_R16_FLOAT; + + case 112: // D3DFMT_G16R16F + return DXGI_FORMAT_R16G16_FLOAT; + + case 113: // D3DFMT_A16B16G16R16F + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case 114: // D3DFMT_R32F + return DXGI_FORMAT_R32_FLOAT; + + case 115: // D3DFMT_G32R32F + return DXGI_FORMAT_R32G32_FLOAT; + + case 116: // D3DFMT_A32B32G32R32F + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + + return DXGI_FORMAT_UNKNOWN; + } + + #undef ISBITMASK + + //-------------------------------------------------------------------------------------- + inline DirectX::DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER* header) + { + if (header->ddspf.flags & DDS_FOURCC) + { + if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC) + { + auto d3d10ext = reinterpret_cast((const char*)header + sizeof(DDS_HEADER)); + auto mode = static_cast(d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK); + switch (mode) + { + case DDS_ALPHA_MODE_STRAIGHT: + case DDS_ALPHA_MODE_PREMULTIPLIED: + case DDS_ALPHA_MODE_OPAQUE: + case DDS_ALPHA_MODE_CUSTOM: + return mode; + } + } + else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC) + || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC)) + { + return DDS_ALPHA_MODE_PREMULTIPLIED; + } + } + + return DDS_ALPHA_MODE_UNKNOWN; + } + + //-------------------------------------------------------------------------------------- + class auto_delete_file + { + public: + auto_delete_file(HANDLE hFile) : m_handle(hFile) {} + + auto_delete_file(const auto_delete_file&) = delete; + auto_delete_file& operator=(const auto_delete_file&) = delete; + + ~auto_delete_file() + { + if (m_handle) + { + FILE_DISPOSITION_INFO info = {}; + info.DeleteFile = TRUE; + (void)SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, sizeof(info)); + } + } + + void clear() { m_handle = 0; } + + private: + HANDLE m_handle; + }; + + class auto_delete_file_wic + { + public: + auto_delete_file_wic(Microsoft::WRL::ComPtr& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {} + + auto_delete_file_wic(const auto_delete_file_wic&) = delete; + auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete; + + ~auto_delete_file_wic() + { + if (m_filename) + { + m_handle.Reset(); + DeleteFileW(m_filename); + } + } + + void clear() { m_filename = 0; } + + private: + LPCWSTR m_filename; + Microsoft::WRL::ComPtr& m_handle; + }; +} \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/Model.cpp b/Kits/DirectXTK12/Src/Model.cpp new file mode 100644 index 00000000..a94bd7c6 --- /dev/null +++ b/Kits/DirectXTK12/Src/Model.cpp @@ -0,0 +1,279 @@ +//-------------------------------------------------------------------------------------- +// File: Model.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Model.h" + +#include "CommonStates.h" +#include "DirectXHelpers.h" +#include "Effects.h" +#include "PlatformHelpers.h" +#include "DescriptorHeap.h" + +using namespace DirectX; + +#ifndef _CPPRTTI +#error Model requires RTTI +#endif + + +//-------------------------------------------------------------------------------------- +// ModelMeshPart +//-------------------------------------------------------------------------------------- + +ModelMeshPart::ModelMeshPart() : + indexCount(0), + startIndex(0), + vertexOffset(0), + vertexStride(0), + primitiveType(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST), + indexFormat(DXGI_FORMAT_R16_UINT), + isAlpha(false) +{ +} + + +ModelMeshPart::~ModelMeshPart() +{ +} + + +_Use_decl_annotations_ +void ModelMeshPart::Draw(_In_ ID3D12GraphicsCommandList* commandList) const +{ + D3D12_VERTEX_BUFFER_VIEW vbv; + vbv.BufferLocation = vertexBuffer.GpuAddress(); + vbv.StrideInBytes = vertexStride; + vbv.SizeInBytes = (UINT)vertexBuffer.Size(); + commandList->IASetVertexBuffers(0, 1, &vbv); + + D3D12_INDEX_BUFFER_VIEW ibv; + ibv.BufferLocation = indexBuffer.GpuAddress(); + ibv.SizeInBytes = (UINT)indexBuffer.Size(); + ibv.Format = indexFormat; + commandList->IASetIndexBuffer(&ibv); + + commandList->IASetPrimitiveTopology(primitiveType); + + commandList->DrawIndexedInstanced( indexCount, 1, startIndex, vertexOffset, 0 ); +} + +_Use_decl_annotations_ +void ModelMeshPart::DrawMeshParts(ID3D12GraphicsCommandList* commandList, const ModelMeshPart::Collection& meshParts) +{ + for ( auto it = meshParts.cbegin(); it != meshParts.cend(); ++it ) + { + auto part = (*it).get(); + assert( part != 0 ); + + part->Draw(commandList); + } +} + + +_Use_decl_annotations_ +void ModelMeshPart::DrawMeshParts(ID3D12GraphicsCommandList* commandList, const ModelMeshPart::Collection& meshParts, ModelMeshPart::DrawCallback callback) +{ + for ( auto it = meshParts.cbegin(); it != meshParts.cend(); ++it ) + { + auto part = (*it).get(); + assert( part != 0 ); + + callback(commandList, *part); + part->Draw(commandList); + } +} + + +_Use_decl_annotations_ +void ModelMeshPart::DrawMeshParts(ID3D12GraphicsCommandList* commandList, const ModelMeshPart::Collection& meshParts, IEffect* effect) +{ + effect->Apply(commandList); + DrawMeshParts(commandList, meshParts); +} + + +//-------------------------------------------------------------------------------------- +// ModelMesh +//-------------------------------------------------------------------------------------- + +ModelMesh::ModelMesh() : + ccw(true), + pmalpha(true) +{ +} + + +ModelMesh::~ModelMesh() +{ +} + +// Draw the mesh +void __cdecl ModelMesh::DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList) const +{ + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts); +} +void __cdecl ModelMesh::DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList) const +{ + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts); +} + +// Draw the mesh with an effect +void __cdecl ModelMesh::DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const +{ + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, effect); +} +void __cdecl ModelMesh::DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, _In_ IEffect* effect) const +{ + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, effect); +} + +// Draw the mesh with a callback for each mesh part +void __cdecl ModelMesh::DrawOpaque(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const +{ + ModelMeshPart::DrawMeshParts(commandList, opaqueMeshParts, callback); +} +void __cdecl ModelMesh::DrawAlpha(_In_ ID3D12GraphicsCommandList* commandList, ModelMeshPart::DrawCallback callback) const +{ + ModelMeshPart::DrawMeshParts(commandList, alphaMeshParts, callback); +} + + +//-------------------------------------------------------------------------------------- +// Model +//-------------------------------------------------------------------------------------- +Model::Model() +{ +} + + +Model::~Model() +{ +} + + +// Load texture resources +void Model::LoadTextures(_In_ IEffectTextureFactory& texFactory, _In_opt_ int destinationDescriptorOffset) +{ + for (size_t i = 0; i < textureNames.size(); ++i) + { + texFactory.CreateTexture(textureNames[i].c_str(), destinationDescriptorOffset + (int) i); + } +} + + +// Load texture resources (helper function) +std::unique_ptr Model::LoadTextures(_In_ ID3D12Device* device, _Inout_ ResourceUploadBatch& resourceUploadBatch, _In_opt_z_ const wchar_t* texturesPath, _In_opt_ D3D12_DESCRIPTOR_HEAP_FLAGS flags) +{ + if (textureNames.size() == 0) + return nullptr; + + std::unique_ptr texFactory = std::make_unique( + device, + resourceUploadBatch, + textureNames.size(), + flags); + if (texturesPath != nullptr && *texturesPath != 0) + { + texFactory->SetDirectory(texturesPath); + } + + LoadTextures(*texFactory); + + return std::move(texFactory); +} + + +// Create effects for each mesh piece +std::vector> Model::CreateEffects( + _In_ IEffectFactory& fxFactory, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_opt_ int descriptorOffset) +{ + std::vector> effects; + effects.reserve(materials.size()); + + for (const auto& mesh : meshes) + { + assert(mesh != nullptr); + + for (const auto& part : mesh->opaqueMeshParts) + { + assert(part != nullptr); + + if (part->materialIndex == ~0ull) + continue; + + effects.push_back(CreateEffectForMeshPart(fxFactory, pipelineState, descriptorOffset, part.get())); + } + + for (const auto& part : mesh->alphaMeshParts) + { + assert(part != nullptr); + + if (part->materialIndex == ~0ull) + continue; + + effects.push_back(CreateEffectForMeshPart(fxFactory, pipelineState, descriptorOffset, part.get())); + } + } + + return std::move(effects); +} + +// Creates an effect for a mesh part +std::shared_ptr Model::CreateEffectForMeshPart( + _In_ IEffectFactory& fxFactory, + _In_ const EffectPipelineStateDescription& pipelineState, + _In_opt_ int descriptorOffset, + _In_ const ModelMeshPart* part) const +{ + assert(part->materialIndex < materials.size()); + + const auto& m = materials[part->materialIndex]; + + D3D12_INPUT_LAYOUT_DESC il = {}; + il.NumElements = (uint32_t) part->vbDecl->size(); + il.pInputElementDescs = part->vbDecl->data(); + + return fxFactory.CreateEffect(m, pipelineState, il, descriptorOffset); +} + +// Create effects for each mesh piece with the default factory +std::vector> Model::CreateEffects( + _In_ const EffectPipelineStateDescription& pipelineState, + _In_ ID3D12DescriptorHeap* gpuVisibleTextureDescriptorHeap, + _In_opt_ int descriptorOffset) +{ + EffectFactory fxFactory(gpuVisibleTextureDescriptorHeap); + return CreateEffects(fxFactory, pipelineState, descriptorOffset); +} + +// Updates effect matrices (if applicable) +void XM_CALLCONV Model::UpdateEffectMatrices( + _In_ std::vector>& effectList, + DirectX::FXMMATRIX world, + DirectX::CXMMATRIX view, + DirectX::CXMMATRIX proj) +{ + for (auto& fx : effectList) + { + IEffectMatrices* matFx = dynamic_cast(fx.get()); + if (matFx != nullptr) + { + matFx->SetWorld(world); + matFx->SetView(view); + matFx->SetProjection(proj); + } + } +} diff --git a/Kits/DirectXTK12/Src/ModelLoadSDKMESH.cpp b/Kits/DirectXTK12/Src/ModelLoadSDKMESH.cpp new file mode 100644 index 00000000..8df725f4 --- /dev/null +++ b/Kits/DirectXTK12/Src/ModelLoadSDKMESH.cpp @@ -0,0 +1,576 @@ +//-------------------------------------------------------------------------------------- +// File: ModelLoadSDKMESH.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Model.h" + +#include "Effects.h" +#include "VertexTypes.h" + +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "BinaryReader.h" +#include "DescriptorHeap.h" + +#include "SDKMesh.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + int GetUniqueTextureIndex(const wchar_t* textureName, std::map& textureDictionary) + { + if (textureName == nullptr || !textureName[0]) + return -1; + + auto i = textureDictionary.find(textureName); + if (i == std::cend(textureDictionary)) + { + int index = (int) textureDictionary.size(); + textureDictionary[textureName] = index; + return index; + } + else + { + return i->second; + } + } + + void InitMaterial( + _In_ const DXUT::SDKMESH_MATERIAL& mh, + _In_ bool perVertexColor, + _In_ bool enableSkinning, + _In_ bool enableDualTexture, + _In_ bool isPremultipliedAlpha, + _Out_ Model::ModelMaterialInfo& m, + _Inout_ std::map& textureDictionary) + { + wchar_t matName[DXUT::MAX_MATERIAL_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.Name, -1, matName, DXUT::MAX_MATERIAL_NAME); + + wchar_t txtName[DXUT::MAX_TEXTURE_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.DiffuseTexture, -1, txtName, DXUT::MAX_TEXTURE_NAME); + + wchar_t txtName2[DXUT::MAX_TEXTURE_NAME]; + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mh.SpecularTexture, -1, txtName2, DXUT::MAX_TEXTURE_NAME); + + if (!mh.SpecularTexture[0] && enableDualTexture) + { + DebugTrace("WARNING: Material '%s' has multiple texture coords but not multiple textures\n", mh.Name); + enableDualTexture = false; + } + + m = {}; + m.name = matName; + m.perVertexColor = perVertexColor; + m.enableSkinning = enableSkinning; + m.enableDualTexture = enableDualTexture; + m.isPremultipliedAlpha = isPremultipliedAlpha; + m.ambientColor = XMFLOAT3(mh.Ambient.x, mh.Ambient.y, mh.Ambient.z); + m.diffuseColor = XMFLOAT3(mh.Diffuse.x, mh.Diffuse.y, mh.Diffuse.z); + m.emissiveColor = XMFLOAT3(mh.Emissive.x, mh.Emissive.y, mh.Emissive.z); + + if (mh.Diffuse.w != 1.f && mh.Diffuse.w != 0.f) + { + m.alphaValue = mh.Diffuse.w; + } + else + m.alphaValue = 1.f; + + if (mh.Power) + { + m.specularPower = mh.Power; + m.specularColor = XMFLOAT3(mh.Specular.x, mh.Specular.y, mh.Specular.z); + } + + m.textureIndex = GetUniqueTextureIndex(txtName, textureDictionary); + m.textureIndex2 = GetUniqueTextureIndex(txtName2, textureDictionary); + } + + + //-------------------------------------------------------------------------------------- + // Direct3D 9 Vertex Declaration to Direct3D 12 Input Layout mapping + + void GetInputLayoutDesc(_In_reads_(32) const DXUT::D3DVERTEXELEMENT9 decl[], std::vector& inputDesc, + bool &perVertexColor, bool& enableSkinning, bool& dualTexture) + { + static const D3D12_INPUT_ELEMENT_DESC elements[] = + { + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "BLENDINDICES",0, DXGI_FORMAT_R8G8B8A8_UINT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "BLENDWEIGHT", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + using namespace DXUT; + + uint32_t offset = 0; + uint32_t texcoords = 0; + + bool posfound = false; + + for (uint32_t index = 0; index < DXUT::MAX_VERTEX_ELEMENTS; ++index) + { + if (decl[index].Usage == 0xFF) + break; + + if (decl[index].Type == D3DDECLTYPE_UNUSED) + break; + + if (decl[index].Offset != offset) + break; + + if (decl[index].Usage == D3DDECLUSAGE_POSITION && decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[0]); + offset += 12; + posfound = true; + } + else if (decl[index].Usage == D3DDECLUSAGE_NORMAL) + { + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[1]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[1]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; + } + else if (decl[index].Usage == D3DDECLUSAGE_COLOR && decl[index].Type == D3DDECLTYPE_D3DCOLOR) + { + inputDesc.push_back(elements[2]); + offset += 4; + perVertexColor = true; + } + else if (decl[index].Usage == D3DDECLUSAGE_TANGENT) + { + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[3]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[3]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; + } + else if (decl[index].Usage == D3DDECLUSAGE_BINORMAL) + { + if (decl[index].Type == D3DDECLTYPE_FLOAT3) + { + inputDesc.push_back(elements[4]); + offset += 12; + } + else if (decl[index].Type == D3DDECLTYPE_FLOAT16_4) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_SHORT4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R16G16B16A16_SNORM; + inputDesc.push_back(desc); + offset += 8; + } + else if (decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[4]; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + inputDesc.push_back(desc); + offset += 4; + } + else + break; + } + else if (decl[index].Usage == D3DDECLUSAGE_TEXCOORD) + { + D3D12_INPUT_ELEMENT_DESC desc = elements[5]; + desc.SemanticIndex = decl[index].UsageIndex; + + bool unk = false; + switch (decl[index].Type) + { + case D3DDECLTYPE_FLOAT2: offset += 8; break; + case D3DDECLTYPE_FLOAT1: desc.Format = DXGI_FORMAT_R32_FLOAT; offset += 4; break; + case D3DDECLTYPE_FLOAT3: desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; offset += 12; break; + case D3DDECLTYPE_FLOAT4: desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; offset += 16; break; + case D3DDECLTYPE_FLOAT16_2: desc.Format = DXGI_FORMAT_R16G16_FLOAT; offset += 4; break; + case D3DDECLTYPE_FLOAT16_4: desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; offset += 8; break; + + default: + unk = true; + break; + } + + if (unk) + break; + + ++texcoords; + + inputDesc.push_back(desc); + } + else if (decl[index].Usage == D3DDECLUSAGE_BLENDINDICES && decl[index].Type == D3DDECLTYPE_UBYTE4) + { + enableSkinning = true; + inputDesc.push_back(elements[6]); + offset += 4; + } + else if (decl[index].Usage == D3DDECLUSAGE_BLENDWEIGHT && decl[index].Type == D3DDECLTYPE_UBYTE4N) + { + enableSkinning = true; + inputDesc.push_back(elements[7]); + offset += 4; + } + else + break; + } + + if (!posfound) + throw std::exception("SV_Position is required"); + + if (texcoords == 2) + { + dualTexture = true; + } + } +} + +//====================================================================================== +// Model Loader +//====================================================================================== + +_Use_decl_annotations_ +std::unique_ptr DirectX::Model::CreateFromSDKMESH( const uint8_t* meshData, size_t dataSize, bool ccw, bool pmalpha ) +{ + if ( !meshData ) + throw std::exception("meshData cannot be null"); + + // File Headers + if ( dataSize < sizeof(DXUT::SDKMESH_HEADER) ) + throw std::exception("End of file"); + auto header = reinterpret_cast( meshData ); + + size_t headerSize = sizeof( DXUT::SDKMESH_HEADER ) + + header->NumVertexBuffers * sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) + + header->NumIndexBuffers * sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER); + if ( header->HeaderSize != headerSize ) + throw std::exception("Not a valid SDKMESH file"); + + if ( dataSize < header->HeaderSize ) + throw std::exception("End of file"); + + if( header->Version != DXUT::SDKMESH_FILE_VERSION ) + throw std::exception("Not a supported SDKMESH version"); + + if ( header->IsBigEndian ) + throw std::exception("Loading BigEndian SDKMESH files not supported"); + + if ( !header->NumMeshes ) + throw std::exception("No meshes found"); + + if ( !header->NumVertexBuffers ) + throw std::exception("No vertex buffers found"); + + if ( !header->NumIndexBuffers ) + throw std::exception("No index buffers found"); + + if ( !header->NumTotalSubsets ) + throw std::exception("No subsets found"); + + if ( !header->NumMaterials ) + throw std::exception("No materials found"); + + // Sub-headers + if ( dataSize < header->VertexStreamHeadersOffset + || ( dataSize < (header->VertexStreamHeadersOffset + header->NumVertexBuffers * sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) ) ) ) + throw std::exception("End of file"); + auto vbArray = reinterpret_cast( meshData + header->VertexStreamHeadersOffset ); + + if ( dataSize < header->IndexStreamHeadersOffset + || ( dataSize < (header->IndexStreamHeadersOffset + header->NumIndexBuffers * sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER) ) ) ) + throw std::exception("End of file"); + auto ibArray = reinterpret_cast( meshData + header->IndexStreamHeadersOffset ); + + if ( dataSize < header->MeshDataOffset + || ( dataSize < (header->MeshDataOffset + header->NumMeshes * sizeof(DXUT::SDKMESH_MESH) ) ) ) + throw std::exception("End of file"); + auto meshArray = reinterpret_cast( meshData + header->MeshDataOffset ); + + if ( dataSize < header->SubsetDataOffset + || ( dataSize < (header->SubsetDataOffset + header->NumTotalSubsets * sizeof(DXUT::SDKMESH_SUBSET) ) ) ) + throw std::exception("End of file"); + auto subsetArray = reinterpret_cast( meshData + header->SubsetDataOffset ); + + if ( dataSize < header->FrameDataOffset + || (dataSize < (header->FrameDataOffset + header->NumFrames * sizeof(DXUT::SDKMESH_FRAME) ) ) ) + throw std::exception("End of file"); + // TODO - auto frameArray = reinterpret_cast( meshData + header->FrameDataOffset ); + + if ( dataSize < header->MaterialDataOffset + || (dataSize < (header->MaterialDataOffset + header->NumMaterials * sizeof(DXUT::SDKMESH_MATERIAL) ) ) ) + throw std::exception("End of file"); + auto materialArray = reinterpret_cast( meshData + header->MaterialDataOffset ); + + // Buffer data + uint64_t bufferDataOffset = header->HeaderSize + header->NonBufferDataSize; + if ( ( dataSize < bufferDataOffset ) + || ( dataSize < bufferDataOffset + header->BufferDataSize ) ) + throw std::exception("End of file"); + const uint8_t* bufferData = meshData + bufferDataOffset; + + // Create vertex buffers + std::vector>> vbDecls; + vbDecls.resize( header->NumVertexBuffers ); + + std::vector perVertexColor; + perVertexColor.resize( header->NumVertexBuffers ); + + std::vector enableSkinning; + enableSkinning.resize( header->NumVertexBuffers ); + + std::vector enableDualTexture; + enableDualTexture.resize( header->NumVertexBuffers ); + + for( UINT j=0; j < header->NumVertexBuffers; ++j ) + { + auto& vh = vbArray[j]; + + if ( dataSize < vh.DataOffset + || ( dataSize < vh.DataOffset + vh.SizeBytes ) ) + throw std::exception("End of file"); + + vbDecls[j] = std::make_shared>(); + bool vertColor = false; + bool skinning = false; + bool dualTexture = false; + GetInputLayoutDesc( vh.Decl, *vbDecls[j].get(), vertColor, skinning, dualTexture ); + perVertexColor[j] = vertColor; + enableSkinning[j] = skinning; + enableDualTexture[j] = dualTexture; + } + + // Validate index buffers + for (UINT j = 0; j < header->NumIndexBuffers; ++j) + { + auto& ih = ibArray[j]; + + if (dataSize < ih.DataOffset + || (dataSize < ih.DataOffset + ih.SizeBytes)) + throw std::exception("End of file"); + + if (ih.IndexType != DXUT::IT_16BIT && ih.IndexType != DXUT::IT_32BIT) + throw std::exception("Invalid index buffer type found"); + } + + // Create meshes + std::vector materials; + materials.resize( header->NumMaterials ); + + std::map textureDictionary; + + std::unique_ptr model(new Model); + model->meshes.reserve( header->NumMeshes ); + + for( UINT meshIndex = 0; meshIndex < header->NumMeshes; ++meshIndex ) + { + auto& mh = meshArray[ meshIndex ]; + + if ( !mh.NumSubsets + || !mh.NumVertexBuffers + || mh.IndexBuffer >= header->NumIndexBuffers + || mh.VertexBuffers[0] >= header->NumVertexBuffers ) + throw std::exception("Invalid mesh found"); + + // mh.NumVertexBuffers is sometimes not what you'd expect, so we skip validating it + + if ( dataSize < mh.SubsetOffset + || (dataSize < mh.SubsetOffset + mh.NumSubsets*sizeof(UINT) ) ) + throw std::exception("End of file"); + + auto subsets = reinterpret_cast( meshData + mh.SubsetOffset ); + + if ( mh.NumFrameInfluences > 0 ) + { + if ( dataSize < mh.FrameInfluenceOffset + || (dataSize < mh.FrameInfluenceOffset + mh.NumFrameInfluences*sizeof(UINT) ) ) + throw std::exception("End of file"); + + // TODO - auto influences = reinterpret_cast( meshData + mh.FrameInfluenceOffset ); + } + + auto mesh = std::make_shared(); + wchar_t meshName[ DXUT::MAX_MESH_NAME ]; + MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, mh.Name, -1, meshName, DXUT::MAX_MESH_NAME ); + mesh->name = meshName; + mesh->ccw = ccw; + mesh->pmalpha = pmalpha; + + // Extents + mesh->boundingBox.Center = mh.BoundingBoxCenter; + mesh->boundingBox.Extents = mh.BoundingBoxExtents; + BoundingSphere::CreateFromBoundingBox( mesh->boundingSphere, mesh->boundingBox ); + + // Create subsets + for( UINT j = 0; j < mh.NumSubsets; ++j ) + { + auto sIndex = subsets[ j ]; + if ( sIndex >= header->NumTotalSubsets ) + throw std::exception("Invalid mesh found"); + + auto& subset = subsetArray[ sIndex ]; + + D3D_PRIMITIVE_TOPOLOGY primType; + switch( subset.PrimitiveType ) + { + case DXUT::PT_TRIANGLE_LIST: primType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case DXUT::PT_TRIANGLE_STRIP: primType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + case DXUT::PT_LINE_LIST: primType = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; + case DXUT::PT_LINE_STRIP: primType = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + case DXUT::PT_POINT_LIST: primType = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; + case DXUT::PT_TRIANGLE_LIST_ADJ: primType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; break; + case DXUT::PT_TRIANGLE_STRIP_ADJ: primType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; break; + case DXUT::PT_LINE_LIST_ADJ: primType = D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; break; + case DXUT::PT_LINE_STRIP_ADJ: primType = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; break; + + case DXUT::PT_QUAD_PATCH_LIST: + case DXUT::PT_TRIANGLE_PATCH_LIST: + throw std::exception("Direct3D9 era tessellation not supported"); + + default: + throw std::exception("Unknown primitive type"); + } + + if ( subset.MaterialID >= header->NumMaterials ) + throw std::exception("Invalid mesh found"); + + auto& mat = materials[ subset.MaterialID ]; + + const size_t vi = mh.VertexBuffers[0]; + InitMaterial(materialArray[subset.MaterialID], + perVertexColor[vi], enableSkinning[vi], enableDualTexture[vi], mesh->pmalpha, + mat, textureDictionary); + + auto part = new ModelMeshPart(); + part->isAlpha = mat.alphaValue < 1.0f; + + const auto& vh = vbArray[mh.VertexBuffers[0]]; + const auto& ih = ibArray[mh.IndexBuffer]; + + part->indexCount = static_cast( subset.IndexCount ); + part->startIndex = static_cast( subset.IndexStart ); + part->vertexOffset = static_cast( subset.VertexStart ); + part->vertexStride = static_cast( vh.StrideBytes ); + part->indexFormat = ( ibArray[ mh.IndexBuffer ].IndexType == DXUT::IT_32BIT ) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; + part->primitiveType = primType; + + // Vertex data + auto verts = reinterpret_cast(bufferData + (vh.DataOffset - bufferDataOffset)); + part->vertexBuffer = GraphicsMemory::Get().Allocate((size_t) vh.SizeBytes); + memcpy(part->vertexBuffer.Memory(), verts, (size_t) vh.SizeBytes); + + // Index data + auto indices = reinterpret_cast(bufferData + (ih.DataOffset - bufferDataOffset)); + part->indexBuffer = GraphicsMemory::Get().Allocate((size_t) ih.SizeBytes); + memcpy(part->indexBuffer.Memory(), indices, (size_t) ih.SizeBytes); + + part->materialIndex = subset.MaterialID; + part->vbDecl = vbDecls[ mh.VertexBuffers[0] ]; + + if (part->isAlpha) + mesh->alphaMeshParts.emplace_back( part ); + else + mesh->opaqueMeshParts.emplace_back( part ); + } + + model->meshes.emplace_back( mesh ); + } + + // Copy the materials and texture names into contiguous arrays + model->materials = std::move(materials); + model->textureNames.resize(textureDictionary.size()); + for (auto texture = std::cbegin(textureDictionary); texture != std::cend(textureDictionary); ++texture) + { + model->textureNames[texture->second] = texture->first; + } + + return model; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +std::unique_ptr DirectX::Model::CreateFromSDKMESH( const wchar_t* szFileName, bool ccw, bool pmalpha ) +{ + size_t dataSize = 0; + std::unique_ptr data; + HRESULT hr = BinaryReader::ReadEntireFile( szFileName, data, &dataSize ); + if ( FAILED(hr) ) + { + DebugTrace( "CreateFromSDKMESH failed (%08X) loading '%ls'\n", hr, szFileName ); + throw std::exception( "CreateFromSDKMESH" ); + } + + auto model = CreateFromSDKMESH( data.get(), dataSize, ccw, pmalpha ); + + model->name = szFileName; + + return model; +} diff --git a/Kits/DirectXTK12/Src/ModelLoadVBO.cpp b/Kits/DirectXTK12/Src/ModelLoadVBO.cpp new file mode 100644 index 00000000..2ec5713a --- /dev/null +++ b/Kits/DirectXTK12/Src/ModelLoadVBO.cpp @@ -0,0 +1,132 @@ +//-------------------------------------------------------------------------------------- +// File: ModelLoadVBO.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Model.h" + +#include "Effects.h" +#include "VertexTypes.h" + +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "BinaryReader.h" + +#include "vbo.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +static_assert(sizeof(VertexPositionNormalTexture) == 32, "VBO vertex size mismatch"); + +namespace +{ + //-------------------------------------------------------------------------------------- + // Shared VB input element description + INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; + std::shared_ptr> g_vbdecl; + + BOOL CALLBACK InitializeDecl(PINIT_ONCE initOnce, PVOID Parameter, PVOID *lpContext) + { + UNREFERENCED_PARAMETER(initOnce); + UNREFERENCED_PARAMETER(Parameter); + UNREFERENCED_PARAMETER(lpContext); + + g_vbdecl = std::make_shared>(VertexPositionNormalTexture::InputLayout.pInputElementDescs, + VertexPositionNormalTexture::InputLayout.pInputElementDescs + VertexPositionNormalTexture::InputLayout.NumElements); + + return TRUE; + } +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +std::unique_ptr DirectX::Model::CreateFromVBO(const uint8_t* meshData, size_t dataSize, bool ccw, bool pmalpha) +{ + if (!InitOnceExecuteOnce(&g_InitOnce, InitializeDecl, nullptr, nullptr)) + throw std::exception("One-time initialization failed"); + + if ( !meshData ) + throw std::exception("meshData cannot be null"); + + // File Header + if ( dataSize < sizeof(VBO::header_t) ) + throw std::exception("End of file"); + auto header = reinterpret_cast( meshData ); + + if ( !header->numVertices || !header->numIndices ) + throw std::exception("No vertices or indices found"); + + size_t vertSize = sizeof(VertexPositionNormalTexture) * header->numVertices; + + if (dataSize < (vertSize + sizeof(VBO::header_t))) + throw std::exception("End of file"); + auto verts = reinterpret_cast( meshData + sizeof(VBO::header_t) ); + + size_t indexSize = sizeof(uint16_t) * header->numIndices; + + if (dataSize < (sizeof(VBO::header_t) + vertSize + indexSize)) + throw std::exception("End of file"); + auto indices = reinterpret_cast( meshData + sizeof(VBO::header_t) + vertSize ); + + // Create vertex buffer + auto vb = GraphicsMemory::Get().Allocate(vertSize); + memcpy(vb.Memory(), verts, vertSize); + + // Create index buffer + auto ib = GraphicsMemory::Get().Allocate(indexSize); + memcpy(ib.Memory(), indices, indexSize); + + auto part = new ModelMeshPart(); + part->indexCount = header->numIndices; + part->startIndex = 0; + part->vertexStride = static_cast( sizeof(VertexPositionNormalTexture) ); + part->indexBuffer = std::move(ib); + part->vertexBuffer = std::move(vb); + part->materialIndex = 0; + part->vbDecl = g_vbdecl; + + auto mesh = std::make_shared(); + mesh->ccw = ccw; + mesh->pmalpha = pmalpha; + BoundingSphere::CreateFromPoints(mesh->boundingSphere, header->numVertices, &verts->position, sizeof(VertexPositionNormalTexture)); + BoundingBox::CreateFromPoints(mesh->boundingBox, header->numVertices, &verts->position, sizeof(VertexPositionNormalTexture)); + mesh->opaqueMeshParts.emplace_back(part); + + std::unique_ptr model(new Model()); + model->meshes.emplace_back(mesh); + + return model; +} + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +std::unique_ptr DirectX::Model::CreateFromVBO(const wchar_t* szFileName, + bool ccw, bool pmalpha) +{ + size_t dataSize = 0; + std::unique_ptr data; + HRESULT hr = BinaryReader::ReadEntireFile( szFileName, data, &dataSize ); + if ( FAILED(hr) ) + { + DebugTrace( "CreateFromVBO failed (%08X) loading '%ls'\n", hr, szFileName ); + throw std::exception( "CreateFromVBO" ); + } + + auto model = CreateFromVBO( data.get(), dataSize, ccw, pmalpha ); + + model->name = szFileName; + + return model; +} diff --git a/Kits/DirectXTK12/Src/Mouse.cpp b/Kits/DirectXTK12/Src/Mouse.cpp new file mode 100644 index 00000000..2f72fb6e --- /dev/null +++ b/Kits/DirectXTK12/Src/Mouse.cpp @@ -0,0 +1,961 @@ +//-------------------------------------------------------------------------------------- +// File: Mouse.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "Mouse.h" + +#include "PlatformHelpers.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) + +//====================================================================================== +// Windows Store or Universal Windows Platform (UWP) app implementation +//====================================================================================== + +// +// For a Windows Store app or Universal Windows Platform (UWP) app, add the following to your existing +// application methods: +// +// void App::SetWindow(CoreWindow^ window ) +// { +// m_mouse->SetWindow(window); +// } +// +// void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) +// { +// m_mouse->SetDpi(sender->LogicalDpi); +// } +// + +#include + +class Mouse::Impl +{ +public: + Impl(Mouse* owner) : + mOwner(owner), + mDPI(96.f), + mMode(MODE_ABSOLUTE) + { + mPointerPressedToken.value = 0; + mPointerReleasedToken.value = 0; + mPointerMovedToken.value = 0; + mPointerWheelToken.value = 0; + mPointerMouseMovedToken.value = 0; + + if ( s_mouse ) + { + throw std::exception( "Mouse is a singleton" ); + } + + s_mouse = this; + + memset( &mState, 0, sizeof(State) ); + + mScrollWheelValue.reset( CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + mRelativeRead.reset( CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + if ( !mScrollWheelValue + || !mRelativeRead ) + { + throw std::exception( "CreateEventEx" ); + } + } + + ~Impl() + { + s_mouse = nullptr; + + RemoveHandlers(); + } + + void GetState(State& state) const + { + memcpy( &state, &mState, sizeof(State) ); + + DWORD result = WaitForSingleObjectEx( mScrollWheelValue.get(), 0, FALSE ); + if ( result == WAIT_FAILED ) + throw std::exception( "WaitForSingleObjectEx" ); + + if ( result == WAIT_OBJECT_0 ) + { + state.scrollWheelValue = 0; + } + + if (mMode == MODE_RELATIVE) + { + result = WaitForSingleObjectEx( mRelativeRead.get(), 0, FALSE ); + + if (result == WAIT_FAILED) + throw std::exception("WaitForSingleObjectEx"); + + if (result == WAIT_OBJECT_0) + { + state.x = 0; + state.y = 0; + } + else + { + SetEvent(mRelativeRead.get()); + } + } + + state.positionMode = mMode; + } + + void ResetScrollWheelValue() + { + SetEvent(mScrollWheelValue.get()); + } + + void SetMode(Mode mode) + { + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::UI::Core; + using namespace ABI::Windows::Foundation; + + if (mMode == mode) + return; + + ComPtr statics; + HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_UI_Core_CoreWindow).Get(), statics.GetAddressOf() ); + ThrowIfFailed( hr ); + + ComPtr window; + hr = statics->GetForCurrentThread( window.GetAddressOf() ); + ThrowIfFailed( hr ); + + if (mode == MODE_RELATIVE) + { + hr = window->get_PointerCursor( mCursor.ReleaseAndGetAddressOf() ); + ThrowIfFailed(hr); + + hr = window->put_PointerCursor(nullptr); + ThrowIfFailed(hr); + + SetEvent(mRelativeRead.get()); + + mMode = MODE_RELATIVE; + } + else + { + if (!mCursor) + { + ComPtr factory; + hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), factory.GetAddressOf() ); + ThrowIfFailed( hr ); + + hr = factory->CreateCursor( CoreCursorType_Arrow, 0, mCursor.GetAddressOf() ); + ThrowIfFailed( hr ); + } + + hr = window->put_PointerCursor( mCursor.Get() ); + ThrowIfFailed(hr); + + mCursor.Reset(); + + mMode = MODE_ABSOLUTE; + } + } + + void SetWindow(ABI::Windows::UI::Core::ICoreWindow* window) + { + using namespace Microsoft::WRL; + using namespace Microsoft::WRL::Wrappers; + using namespace ABI::Windows::Foundation; + using namespace ABI::Windows::Devices::Input; + + if (mWindow.Get() == window) + return; + + RemoveHandlers(); + + mWindow = window; + + if (!window) + { + mCursor.Reset(); + mMouse.Reset(); + return; + } + + ComPtr mouseStatics; + HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_Devices_Input_MouseDevice).Get(), mouseStatics.GetAddressOf() ); + ThrowIfFailed( hr ); + + hr = mouseStatics->GetForCurrentView(mMouse.ReleaseAndGetAddressOf()); + ThrowIfFailed(hr); + + typedef __FITypedEventHandler_2_Windows__CDevices__CInput__CMouseDevice_Windows__CDevices__CInput__CMouseEventArgs MouseMovedHandler; + hr = mMouse->add_MouseMoved( Callback(MouseMovedEvent).Get(), &mPointerMouseMovedToken ); + ThrowIfFailed(hr); + + typedef __FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs PointerHandler; + auto cb = Callback(PointerEvent); + + hr = window->add_PointerPressed(cb.Get(), &mPointerPressedToken); + ThrowIfFailed(hr); + + hr = window->add_PointerReleased(cb.Get(), &mPointerReleasedToken); + ThrowIfFailed(hr); + + hr = window->add_PointerMoved(cb.Get(), &mPointerMovedToken); + ThrowIfFailed(hr); + + hr = window->add_PointerWheelChanged(Callback(PointerWheel).Get(), &mPointerWheelToken); + ThrowIfFailed(hr); + } + + State mState; + float mDPI; + Mouse* mOwner; + + static Mouse::Impl* s_mouse; + +private: + Mode mMode; + + ComPtr mWindow; + ComPtr mMouse; + ComPtr mCursor; + + ScopedHandle mScrollWheelValue; + ScopedHandle mRelativeRead; + + EventRegistrationToken mPointerPressedToken; + EventRegistrationToken mPointerReleasedToken; + EventRegistrationToken mPointerMovedToken; + EventRegistrationToken mPointerWheelToken; + EventRegistrationToken mPointerMouseMovedToken; + + void RemoveHandlers() + { + if (mWindow) + { + mWindow->remove_PointerPressed(mPointerPressedToken); + mPointerPressedToken.value = 0; + + mWindow->remove_PointerReleased(mPointerReleasedToken); + mPointerReleasedToken.value = 0; + + mWindow->remove_PointerMoved(mPointerMovedToken); + mPointerMovedToken.value = 0; + + mWindow->remove_PointerWheelChanged(mPointerWheelToken); + mPointerWheelToken.value = 0; + } + + if (mMouse) + { + mMouse->remove_MouseMoved(mPointerMouseMovedToken); + mPointerMouseMovedToken.value = 0; + } + } + + static HRESULT PointerEvent( IInspectable *, ABI::Windows::UI::Core::IPointerEventArgs*args ) + { + using namespace ABI::Windows::Foundation; + using namespace ABI::Windows::UI::Input; + using namespace ABI::Windows::Devices::Input; + + if (!s_mouse) + return S_OK; + + ComPtr currentPoint; + HRESULT hr = args->get_CurrentPoint( currentPoint.GetAddressOf() ); + ThrowIfFailed(hr); + + ComPtr pointerDevice; + hr = currentPoint->get_PointerDevice( pointerDevice.GetAddressOf() ); + ThrowIfFailed(hr); + + PointerDeviceType devType; + hr = pointerDevice->get_PointerDeviceType( &devType ); + ThrowIfFailed(hr); + + if (devType == PointerDeviceType::PointerDeviceType_Mouse) + { + ComPtr props; + hr = currentPoint->get_Properties( props.GetAddressOf() ); + ThrowIfFailed(hr); + + boolean value; + hr = props->get_IsLeftButtonPressed(&value); + ThrowIfFailed(hr); + s_mouse->mState.leftButton = value != 0; + + hr = props->get_IsRightButtonPressed(&value); + ThrowIfFailed(hr); + s_mouse->mState.rightButton = value != 0; + + hr = props->get_IsMiddleButtonPressed(&value); + ThrowIfFailed(hr); + s_mouse->mState.middleButton = value != 0; + + hr = props->get_IsXButton1Pressed(&value); + ThrowIfFailed(hr); + s_mouse->mState.xButton1 = value != 0; + + hr = props->get_IsXButton2Pressed(&value); + ThrowIfFailed(hr); + s_mouse->mState.xButton2 = value != 0; + } + + if (s_mouse->mMode == MODE_ABSOLUTE) + { + Point pos; + hr = currentPoint->get_Position( &pos ); + ThrowIfFailed(hr); + + float dpi = s_mouse->mDPI; + + s_mouse->mState.x = static_cast( pos.X * dpi / 96.f + 0.5f ); + s_mouse->mState.y = static_cast( pos.Y * dpi / 96.f + 0.5f ); + } + + return S_OK; + } + + static HRESULT PointerWheel( IInspectable *, ABI::Windows::UI::Core::IPointerEventArgs*args ) + { + using namespace ABI::Windows::Foundation; + using namespace ABI::Windows::UI::Input; + using namespace ABI::Windows::Devices::Input; + + if (!s_mouse) + return S_OK; + + ComPtr currentPoint; + HRESULT hr = args->get_CurrentPoint( currentPoint.GetAddressOf() ); + ThrowIfFailed(hr); + + ComPtr pointerDevice; + hr = currentPoint->get_PointerDevice( pointerDevice.GetAddressOf() ); + ThrowIfFailed(hr); + + PointerDeviceType devType; + hr = pointerDevice->get_PointerDeviceType( &devType ); + ThrowIfFailed(hr); + + if (devType == PointerDeviceType::PointerDeviceType_Mouse) + { + ComPtr props; + hr = currentPoint->get_Properties( props.GetAddressOf() ); + ThrowIfFailed(hr); + + INT32 value; + hr = props->get_MouseWheelDelta(&value); + ThrowIfFailed(hr); + + HANDLE evt = s_mouse->mScrollWheelValue.get(); + if (WaitForSingleObjectEx(evt, 0, FALSE) == WAIT_OBJECT_0) + { + s_mouse->mState.scrollWheelValue = 0; + ResetEvent(evt); + } + + s_mouse->mState.scrollWheelValue += value; + + if (s_mouse->mMode == MODE_ABSOLUTE) + { + Point pos; + hr = currentPoint->get_Position( &pos ); + ThrowIfFailed(hr); + + float dpi = s_mouse->mDPI; + + s_mouse->mState.x = static_cast( pos.X * dpi / 96.f + 0.5f ); + s_mouse->mState.y = static_cast( pos.Y * dpi / 96.f + 0.5f ); + } + } + + return S_OK; + } + + static HRESULT MouseMovedEvent( IInspectable *, ABI::Windows::Devices::Input::IMouseEventArgs* args ) + { + using namespace ABI::Windows::Devices::Input; + + if (!s_mouse) + return S_OK; + + if (s_mouse->mMode == MODE_RELATIVE) + { + MouseDelta delta; + HRESULT hr = args->get_MouseDelta(&delta); + ThrowIfFailed(hr); + + s_mouse->mState.x = delta.X; + s_mouse->mState.y = delta.Y; + + ResetEvent( s_mouse->mRelativeRead.get() ); + } + + return S_OK; + } +}; + + +Mouse::Impl* Mouse::Impl::s_mouse = nullptr; + + +void Mouse::SetWindow(ABI::Windows::UI::Core::ICoreWindow* window) +{ + pImpl->SetWindow(window); +} + + +void Mouse::SetDpi(float dpi) +{ + auto pImpl = Impl::s_mouse; + + if (!pImpl) + return; + + pImpl->mDPI = dpi; +} + + +#elif defined(_XBOX_ONE) || ( defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ) + +//====================================================================================== +// Null device for Windows Phone and Xbox One +//====================================================================================== + +class Mouse::Impl +{ +public: + Impl(Mouse* owner) : + mOwner(owner) + { + if ( s_mouse ) + { + throw std::exception( "Mouse is a singleton" ); + } + + s_mouse = this; + } + + ~Impl() + { + s_mouse = nullptr; + } + + void GetState(State& state) const + { + memset( &state, 0, sizeof(State) ); + } + + void ResetScrollWheelValue() + { + } + + void SetMode(Mode mode) + { + UNREFERENCED_PARAMETER(mode); + } + + Mouse* mOwner; + + static Mouse::Impl* s_mouse; +}; + +Mouse::Impl* Mouse::Impl::s_mouse = nullptr; + +#else + +//====================================================================================== +// Win32 desktop implementation +//====================================================================================== + +// +// For a Win32 desktop application, in your window setup be sure to call this method: +// +// m_mouse->SetWindow(hwnd); +// +// And call this static function from your Window Message Procedure +// +// LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +// { +// switch (message) +// { +// case WM_ACTIVATEAPP: +// case WM_INPUT: +// case WM_MOUSEMOVE: +// case WM_LBUTTONDOWN: +// case WM_LBUTTONUP: +// case WM_RBUTTONDOWN: +// case WM_RBUTTONUP: +// case WM_MBUTTONDOWN: +// case WM_MBUTTONUP: +// case WM_MOUSEWHEEL: +// case WM_XBUTTONDOWN: +// case WM_XBUTTONUP: +// case WM_MOUSEHOVER: +// Mouse::ProcessMessage(message, wParam, lParam); +// break; +// +// } +// } +// + +class Mouse::Impl +{ +public: + Impl(Mouse* owner) : + mOwner(owner), + mMode(MODE_ABSOLUTE), + mLastX(0), + mLastY(0), + mInFocus(true) + { + if ( s_mouse ) + { + throw std::exception( "Mouse is a singleton" ); + } + + s_mouse = this; + + memset( &mState, 0, sizeof(State) ); + + mScrollWheelValue.reset( CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + mRelativeRead.reset( CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + mAbsoluteMode.reset( CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + mRelativeMode.reset( CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE) ); + if ( !mScrollWheelValue + || !mRelativeRead + || !mAbsoluteMode + || !mRelativeMode ) + { + throw std::exception( "CreateEventEx" ); + } + } + + ~Impl() + { + s_mouse = nullptr; + } + + void GetState(State& state) const + { + memcpy( &state, &mState, sizeof(State) ); + state.positionMode = mMode; + + DWORD result = WaitForSingleObjectEx( mScrollWheelValue.get(), 0, FALSE ); + if ( result == WAIT_FAILED ) + throw std::exception( "WaitForSingleObjectEx" ); + + if ( result == WAIT_OBJECT_0 ) + { + state.scrollWheelValue = 0; + } + + if (state.positionMode == MODE_RELATIVE) + { + result = WaitForSingleObjectEx( mRelativeRead.get(), 0, FALSE ); + + if (result == WAIT_FAILED) + throw std::exception("WaitForSingleObjectEx"); + + if (result == WAIT_OBJECT_0) + { + state.x = 0; + state.y = 0; + } + else + { + SetEvent(mRelativeRead.get()); + } + } + } + + void ResetScrollWheelValue() + { + SetEvent(mScrollWheelValue.get()); + } + + void SetMode(Mode mode) + { + if (mMode == mode) + return; + + SetEvent((mode == MODE_ABSOLUTE) ? mAbsoluteMode.get() : mRelativeMode.get()); + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_HOVER; + tme.hwndTrack = mWindow; + tme.dwHoverTime = 1; + if (!TrackMouseEvent(&tme)) + { + throw std::exception("TrackMouseEvent"); + } + } + + void SetWindow(HWND window) + { + if (mWindow == window) + return; + + RAWINPUTDEVICE Rid; + Rid.usUsagePage = 0x1 /* HID_USAGE_PAGE_GENERIC */; + Rid.usUsage = 0x2 /* HID_USAGE_GENERIC_MOUSE */; + Rid.dwFlags = RIDEV_INPUTSINK; + Rid.hwndTarget = window; + if ( !RegisterRawInputDevices(&Rid, 1, sizeof(RAWINPUTDEVICE)) ) + { + throw std::exception("RegisterRawInputDevices"); + } + + mWindow = window; + } + + State mState; + + Mouse* mOwner; + + static Mouse::Impl* s_mouse; + +private: + HWND mWindow; + Mode mMode; + + ScopedHandle mScrollWheelValue; + ScopedHandle mRelativeRead; + ScopedHandle mAbsoluteMode; + ScopedHandle mRelativeMode; + + int mLastX; + int mLastY; + + bool mInFocus; + + friend void Mouse::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam); + + void ClipToWindow() + { + RECT rect; + GetClientRect(mWindow, &rect); + + POINT ul; + ul.x = rect.left; + ul.y = rect.top; + + POINT lr; + lr.x = rect.right; + lr.y = rect.bottom; + + MapWindowPoints(mWindow, nullptr, &ul, 1); + MapWindowPoints(mWindow, nullptr, &lr, 1); + + rect.left = ul.x; + rect.top = ul.y; + + rect.right = lr.x; + rect.bottom = lr.y; + + ClipCursor(&rect); + } +}; + + +Mouse::Impl* Mouse::Impl::s_mouse = nullptr; + + +void Mouse::SetWindow( HWND window ) +{ + pImpl->SetWindow(window); +} + + +void Mouse::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + auto pImpl = Impl::s_mouse; + + if (!pImpl) + return; + + HANDLE evts[3]; + evts[0] = pImpl->mScrollWheelValue.get(); + evts[1] = pImpl->mAbsoluteMode.get(); + evts[2] = pImpl->mRelativeMode.get(); + switch (WaitForMultipleObjectsEx(_countof(evts), evts, FALSE, 0, FALSE)) + { + case WAIT_OBJECT_0: + pImpl->mState.scrollWheelValue = 0; + ResetEvent(evts[0]); + break; + + case (WAIT_OBJECT_0 + 1) : + { + pImpl->mMode = MODE_ABSOLUTE; + ClipCursor(nullptr); + + POINT point; + point.x = pImpl->mLastX; + point.y = pImpl->mLastY; + if (MapWindowPoints(pImpl->mWindow, nullptr, &point, 1)) + { + SetCursorPos(point.x, point.y); + } + ShowCursor(TRUE); + pImpl->mState.x = pImpl->mLastX; + pImpl->mState.y = pImpl->mLastY; + } + break; + + case (WAIT_OBJECT_0 + 2) : + { + ResetEvent( pImpl->mRelativeRead.get() ); + + pImpl->mMode = MODE_RELATIVE; + pImpl->mState.x = pImpl->mState.y = 0; + + ShowCursor(FALSE); + + pImpl->ClipToWindow(); + } + break; + + case WAIT_FAILED: + throw std::exception("WaitForMultipleObjectsEx"); + } + + switch (message) + { + case WM_ACTIVATEAPP: + if (wParam) + { + pImpl->mInFocus = true; + + if (pImpl->mMode == MODE_RELATIVE) + { + pImpl->mState.x = pImpl->mState.y = 0; + + ShowCursor(FALSE); + + pImpl->ClipToWindow(); + } + } + else + { + int scrollWheel = pImpl->mState.scrollWheelValue; + memset(&pImpl->mState, 0, sizeof(State)); + pImpl->mState.scrollWheelValue = scrollWheel; + + pImpl->mInFocus = false; + } + return; + + case WM_INPUT: + if (pImpl->mInFocus && pImpl->mMode == MODE_RELATIVE) + { + RAWINPUT raw; + UINT rawSize = sizeof(raw); + + UINT resultData = GetRawInputData(reinterpret_cast(lParam), RID_INPUT, &raw, &rawSize, sizeof(RAWINPUTHEADER)); + if (resultData == UINT(-1)) + { + throw std::exception("GetRawInputData"); + } + + if (raw.header.dwType == RIM_TYPEMOUSE) + { + if ( !(raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) ) + { + pImpl->mState.x = raw.data.mouse.lLastX; + pImpl->mState.y = raw.data.mouse.lLastY; + + ResetEvent( pImpl->mRelativeRead.get() ); + } + + // Note that with Remote Desktop input comes through as MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP, + // so this imlementation doesn't suport relative mode via remote desktop. + } + } + return; + + case WM_MOUSEMOVE: + break; + + case WM_LBUTTONDOWN: + pImpl->mState.leftButton = true; + break; + + case WM_LBUTTONUP: + pImpl->mState.leftButton = false; + break; + + case WM_RBUTTONDOWN: + pImpl->mState.rightButton = true; + break; + + case WM_RBUTTONUP: + pImpl->mState.rightButton = false; + break; + + case WM_MBUTTONDOWN: + pImpl->mState.middleButton = true; + break; + + case WM_MBUTTONUP: + pImpl->mState.middleButton = false; + break; + + case WM_MOUSEWHEEL: + pImpl->mState.scrollWheelValue += GET_WHEEL_DELTA_WPARAM(wParam); + return; + + case WM_XBUTTONDOWN: + switch (GET_XBUTTON_WPARAM(wParam)) + { + case XBUTTON1: + pImpl->mState.xButton1 = true; + break; + + case XBUTTON2: + pImpl->mState.xButton2 = true; + break; + } + break; + + case WM_XBUTTONUP: + switch (GET_XBUTTON_WPARAM(wParam)) + { + case XBUTTON1: + pImpl->mState.xButton1 = false; + break; + + case XBUTTON2: + pImpl->mState.xButton2 = false; + break; + } + break; + + case WM_MOUSEHOVER: + break; + + default: + // Not a mouse message, so exit + return; + } + + if (pImpl->mMode == MODE_ABSOLUTE) + { + // All mouse messages provide a new pointer position + int xPos = static_cast(LOWORD(lParam)); // GET_X_LPARAM(lParam); + int yPos = static_cast(HIWORD(lParam)); // GET_Y_LPARAM(lParam); + + pImpl->mState.x = pImpl->mLastX = xPos; + pImpl->mState.y = pImpl->mLastY = yPos; + } +} + +#endif + +#pragma warning( disable : 4355 ) + +// Public constructor. +Mouse::Mouse() + : pImpl( new Impl(this) ) +{ +} + + +// Move constructor. +Mouse::Mouse(Mouse&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ + pImpl->mOwner = this; +} + + +// Move assignment. +Mouse& Mouse::operator= (Mouse&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + pImpl->mOwner = this; + return *this; +} + + +// Public destructor. +Mouse::~Mouse() +{ +} + + +Mouse::State Mouse::GetState() const +{ + State state; + pImpl->GetState(state); + return state; +} + + +void Mouse::ResetScrollWheelValue() +{ + pImpl->ResetScrollWheelValue(); +} + + +void Mouse::SetMode(Mode mode) +{ + pImpl->SetMode(mode); +} + + +Mouse& Mouse::Get() +{ + if ( !Impl::s_mouse || !Impl::s_mouse->mOwner ) + throw std::exception( "Mouse is a singleton" ); + + return *Impl::s_mouse->mOwner; +} + + + +//====================================================================================== +// ButtonStateTracker +//====================================================================================== + +#define UPDATE_BUTTON_STATE(field) field = static_cast( ( !!state.field ) | ( ( !!state.field ^ !!lastState.field ) << 1 ) ); + +void Mouse::ButtonStateTracker::Update( const Mouse::State& state ) +{ + UPDATE_BUTTON_STATE(leftButton); + + assert( ( !state.leftButton && !lastState.leftButton ) == ( leftButton == UP ) ); + assert( ( state.leftButton && lastState.leftButton ) == ( leftButton == HELD ) ); + assert( ( !state.leftButton && lastState.leftButton ) == ( leftButton == RELEASED ) ); + assert( ( state.leftButton && !lastState.leftButton ) == ( leftButton == PRESSED ) ); + + UPDATE_BUTTON_STATE(middleButton); + UPDATE_BUTTON_STATE(rightButton); + UPDATE_BUTTON_STATE(xButton1); + UPDATE_BUTTON_STATE(xButton2); + + lastState = state; +} + +#undef UPDATE_BUTTON_STATE + + +void Mouse::ButtonStateTracker::Reset() +{ + memset( this, 0, sizeof(ButtonStateTracker) ); +} diff --git a/Kits/DirectXTK12/Src/PlatformHelpers.h b/Kits/DirectXTK12/Src/PlatformHelpers.h new file mode 100644 index 00000000..823ec187 --- /dev/null +++ b/Kits/DirectXTK12/Src/PlatformHelpers.h @@ -0,0 +1,152 @@ +//-------------------------------------------------------------------------------------- +// File: PlatformHelpers.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#pragma warning(disable : 4324) + +#include +#include + + +namespace DirectX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } + + + // Helper for output debug tracing + inline void DebugTrace( _In_z_ _Printf_format_string_ const char* format, ... ) + { +#ifdef _DEBUG + va_list args; + va_start( args, format ); + + char buff[1024] = {}; + vsprintf_s( buff, format, args ); + OutputDebugStringA( buff ); + va_end( args ); +#else + UNREFERENCED_PARAMETER( format ); +#endif + } + + + // Helper smart-pointers +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10) || (defined(_XBOX_ONE) && defined(_TITLE)) || !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) + struct virtual_deleter { void operator()(void* p) { if (p) VirtualFree(p, 0, MEM_RELEASE); } }; +#endif + + struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } }; + + struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; + + typedef public std::unique_ptr ScopedHandle; + + inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; } +} + + +#ifdef DIRECTX_EMULATE_MUTEX + +// Emulate the C++0x mutex and lock_guard types when building with Visual Studio CRT versions < 2012. +namespace std +{ + class mutex + { + public: + mutex() { InitializeCriticalSection(&mCriticalSection); } + ~mutex() { DeleteCriticalSection(&mCriticalSection); } + + void lock() { EnterCriticalSection(&mCriticalSection); } + void unlock() { LeaveCriticalSection(&mCriticalSection); } + bool try_lock() { return TryEnterCriticalSection(&mCriticalSection) != 0; } + + private: + CRITICAL_SECTION mCriticalSection; + + mutex(mutex const&); + mutex& operator= (mutex const&); + }; + + + template + class lock_guard + { + public: + typedef Mutex mutex_type; + + explicit lock_guard(mutex_type& mutex) + : mMutex(mutex) + { + mMutex.lock(); + } + + ~lock_guard() + { + mMutex.unlock(); + } + + private: + mutex_type& mMutex; + + lock_guard(lock_guard const&); + lock_guard& operator= (lock_guard const&); + }; +} + +#else + +#include + +#endif + + +#ifdef DIRECTX_EMULATE_MAKE_UNIQUE + +// Emulate make_unique when building with Visual Studio CRT versions < 2012. +namespace std +{ + + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } + +} + +#endif \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/PrimitiveBatch.cpp b/Kits/DirectXTK12/Src/PrimitiveBatch.cpp new file mode 100644 index 00000000..2f1a6865 --- /dev/null +++ b/Kits/DirectXTK12/Src/PrimitiveBatch.cpp @@ -0,0 +1,282 @@ +//-------------------------------------------------------------------------------------- +// File: PrimitiveBatch.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "PrimitiveBatch.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "GraphicsMemory.h" + +using namespace DirectX; +using namespace DirectX::Internal; +using Microsoft::WRL::ComPtr; + + +// Internal PrimitiveBatch implementation class. +class PrimitiveBatchBase::Impl +{ +public: + Impl(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize); + + void Begin( _In_ ID3D12GraphicsCommandList* cmdList ); + void End(); + + void Draw(D3D_PRIMITIVE_TOPOLOGY topology, bool isIndexed, _In_opt_count_(indexCount) uint16_t const* indices, size_t indexCount, size_t vertexCount, _Outptr_ void** pMappedVertices); + +private: + void FlushBatch(); + + GraphicsResource mVertexSegment; + GraphicsResource mIndexSegment; + + ComPtr mDevice; + ComPtr mCommandList; + + size_t mMaxIndices; + size_t mMaxVertices; + size_t mVertexSize; + size_t mVertexPageSize; + size_t mIndexPageSize; + + bool mInBeginEndPair; + + D3D_PRIMITIVE_TOPOLOGY mCurrentTopology; + bool mCurrentlyIndexed; + + size_t mIndexCount; + size_t mVertexCount; + + size_t mBaseIndex; + size_t mBaseVertex; +}; + + +// Constructor. +PrimitiveBatchBase::Impl::Impl(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize) + : mCommandList(nullptr), + mDevice(device), + mMaxIndices(maxIndices), + mMaxVertices(maxVertices), + mVertexSize(vertexSize), + mVertexPageSize(maxVertices * vertexSize), + mIndexPageSize(maxIndices * sizeof(uint16_t)), + mInBeginEndPair(false), + mCurrentTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED), + mCurrentlyIndexed(false), + mIndexCount(0), + mVertexCount(0) +{ + if (maxVertices == 0) + throw std::exception("maxVertices must be greater than 0"); +} + + +// Begins a batch of primitive drawing operations. + +void PrimitiveBatchBase::Impl::Begin( _In_ ID3D12GraphicsCommandList* cmdList ) +{ + if (mInBeginEndPair) + throw std::exception("Cannot nest Begin calls"); + + mCommandList = cmdList; + mInBeginEndPair = true; +} + + +// Ends a batch of primitive drawing operations. +void PrimitiveBatchBase::Impl::End() +{ + if (!mInBeginEndPair) + throw std::exception("Begin must be called before End"); + + FlushBatch(); + + // Release our smart pointers and end the block + mIndexSegment.Reset(); + mVertexSegment.Reset(); + mCommandList.Reset(); + mInBeginEndPair = false; +} + + +// Can we combine adjacent primitives using this topology into a single draw call? +static bool CanBatchPrimitives(D3D_PRIMITIVE_TOPOLOGY topology) +{ + switch (topology) + { + case D3D_PRIMITIVE_TOPOLOGY_POINTLIST: + case D3D_PRIMITIVE_TOPOLOGY_LINELIST: + case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST: + // Lists can easily be merged. + return true; + + default: + // Strips cannot. + return false; + } + + // We could also merge indexed strips by inserting degenerates, + // but that's not always a perf win, so let's keep things simple. +} + + +// Adds new geometry to the batch. +_Use_decl_annotations_ +void PrimitiveBatchBase::Impl::Draw(D3D_PRIMITIVE_TOPOLOGY topology, bool isIndexed, uint16_t const* indices, size_t indexCount, size_t vertexCount, void** pMappedVertices) +{ + if (isIndexed && !indices) + throw std::exception("Indices cannot be null"); + + if (indexCount >= mMaxIndices) + throw std::exception("Too many indices"); + + if (vertexCount >= mMaxVertices) + throw std::exception("Too many vertices"); + + if (!mInBeginEndPair) + throw std::exception("Begin must be called before Draw"); + + assert(pMappedVertices != nullptr); + + // Can we merge this primitive in with an existing batch, or must we flush first? + bool wrapIndexBuffer = (mIndexCount + indexCount > mMaxIndices); + bool wrapVertexBuffer = (mVertexCount + vertexCount > mMaxVertices); + + if ((topology != mCurrentTopology) || + (isIndexed != mCurrentlyIndexed) || + !CanBatchPrimitives(topology) || + wrapIndexBuffer || wrapVertexBuffer) + { + FlushBatch(); + } + + // If we are not already in a batch, lock the buffers. + if (mCurrentTopology == D3D_PRIMITIVE_TOPOLOGY_UNDEFINED) + { + mIndexCount = 0; + mVertexCount = 0; + mBaseIndex = 0; + mBaseVertex = 0; + mCurrentTopology = topology; + mCurrentlyIndexed = isIndexed; + + // Allocate a page for the primitive data + if (isIndexed) + mIndexSegment = GraphicsMemory::Get().Allocate(mIndexPageSize); + + mVertexSegment = GraphicsMemory::Get().Allocate(mVertexPageSize); + } + + // Copy over the index data. + if (isIndexed) + { + uint16_t* outputIndices = (uint16_t*)mIndexSegment.Memory() + mIndexCount; + + for (size_t i = 0; i < indexCount; i++) + { + outputIndices[i] = (uint16_t)(indices[i] + mVertexCount - mBaseIndex); + } + + mIndexCount += indexCount; + } + + // Return the output vertex data location. + *pMappedVertices = (uint8_t*)mVertexSegment.Memory() + mVertexSize * mVertexCount; + + mVertexCount += vertexCount; +} + + +// Sends queued primitives to the graphics device. +void PrimitiveBatchBase::Impl::FlushBatch() +{ + // Early out if there is nothing to flush. + if (mCurrentTopology == D3D_PRIMITIVE_TOPOLOGY_UNDEFINED) + return; + + mCommandList->IASetPrimitiveTopology(mCurrentTopology); + + // Set the vertex buffer view + D3D12_VERTEX_BUFFER_VIEW vbv; + vbv.BufferLocation = mVertexSegment.GpuAddress(); + vbv.SizeInBytes = (UINT) ( mVertexSize * (mVertexCount - mBaseVertex) ); + vbv.StrideInBytes = (UINT) mVertexSize; + mCommandList->IASetVertexBuffers(0, 1, &vbv); + + if (mCurrentlyIndexed) + { + // Set the index buffer view + D3D12_INDEX_BUFFER_VIEW ibv; + ibv.BufferLocation = mIndexSegment.GpuAddress(); + ibv.Format = DXGI_FORMAT_R16_UINT; + ibv.SizeInBytes = (UINT) (mIndexCount - mBaseIndex) * sizeof(uint16_t); + mCommandList->IASetIndexBuffer(&ibv); + + // Draw indexed geometry. + mCommandList->DrawIndexedInstanced((UINT)(mIndexCount - mBaseIndex), 1, 0, 0, 0); + } + else + { + // Draw non-indexed geometry. + mCommandList->DrawInstanced((UINT)(mVertexCount - mBaseVertex), 1, 0, 0); + } + + mCurrentTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + + +// Public constructor. +PrimitiveBatchBase::PrimitiveBatchBase(_In_ ID3D12Device* device, size_t maxIndices, size_t maxVertices, size_t vertexSize) + : pImpl(new Impl(device, maxIndices, maxVertices, vertexSize)) +{ +} + + +// Move constructor. +PrimitiveBatchBase::PrimitiveBatchBase(PrimitiveBatchBase&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +PrimitiveBatchBase& PrimitiveBatchBase::operator= (PrimitiveBatchBase&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +PrimitiveBatchBase::~PrimitiveBatchBase() +{ +} + + +void PrimitiveBatchBase::Begin( _In_ ID3D12GraphicsCommandList* cmdList ) +{ + pImpl->Begin( cmdList ); +} + + +void PrimitiveBatchBase::End() +{ + pImpl->End(); +} + + +_Use_decl_annotations_ +void PrimitiveBatchBase::Draw(D3D12_PRIMITIVE_TOPOLOGY topology, bool isIndexed, uint16_t const* indices, size_t indexCount, size_t vertexCount, void** pMappedVertices) +{ + pImpl->Draw(topology, isIndexed, indices, indexCount, vertexCount, pMappedVertices); +} diff --git a/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp new file mode 100644 index 00000000..6a7c05e7 --- /dev/null +++ b/Kits/DirectXTK12/Src/ResourceUploadBatch.cpp @@ -0,0 +1,589 @@ +//-------------------------------------------------------------------------------------- +// File: ResourceUploadBatch.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "ResourceUploadBatch.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace DirectX +{ + uint32_t CountMips(uint32_t width, uint32_t height) + { + if (width == 0 || height == 0) + return 0; + + uint32_t count = 1; + while (width > 1 || height > 1) + { + width >>= 1; + height >>= 1; + count++; + } + return count; + } +} + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) +# include "Shaders/Compiled/XboxOneGenerateMips_main.inc" +#else +# include "Shaders/Compiled/GenerateMips_main.inc" +#endif + + DXGI_FORMAT ConvertSRVtoUAVFormat(DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_UNORM; + + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_R32_FLOAT: + return DXGI_FORMAT_R32_FLOAT; + + default: + return format; + } + } + + class GenerateMipsResources + { + public: + enum RootParameterIndex + { + Constants, + SourceTexture, + TargetTexture, + RootParameterCount + }; + +#pragma pack(push, 4) + struct ConstantData + { + XMFLOAT2 InvOutTexelSize; + uint32_t SrcMipIndex; + }; +#pragma pack(pop) + + static const uint32_t Num32BitConstants = (uint32_t)(sizeof(ConstantData) / sizeof(uint32_t)); + static const uint32_t ThreadGroupSize = 8; + + ComPtr rootSignature; + ComPtr generateMipsPSO; + + GenerateMipsResources( + _In_ ID3D12Device* device) + { + rootSignature = CreateGenMipsRootSignature(device); + generateMipsPSO = CreateGenMipsPipelineState(device, rootSignature.Get(), GenerateMips_main, sizeof(GenerateMips_main)); + } + + private: + static ComPtr CreateGenMipsRootSignature( + _In_ ID3D12Device* device) + { + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC sampler( + 0, // register + D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP); + + CD3DX12_DESCRIPTOR_RANGE sourceDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_DESCRIPTOR_RANGE targetDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); + + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::Constants].InitAsConstants(Num32BitConstants, 0); + rootParameters[RootParameterIndex::SourceTexture].InitAsDescriptorTable(1, &sourceDescriptorRange); + rootParameters[RootParameterIndex::TargetTexture].InitAsDescriptorTable(1, &targetDescriptorRange); + + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ComPtr rootSignature; + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, rootSignature.ReleaseAndGetAddressOf())); + + SetDebugObjectName(rootSignature.Get(), L"GenerateMips RootSignature"); + + return rootSignature; + } + + static ComPtr CreateGenMipsPipelineState( + _In_ ID3D12Device* device, + _In_ ID3D12RootSignature* rootSignature, + _In_reads_(bytecodeSize) const uint8_t* bytecode, + _In_ size_t bytecodeSize) + { + D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {}; + desc.CS.BytecodeLength = bytecodeSize; + desc.CS.pShaderBytecode = bytecode; +#if !defined(_XBOX_ONE) || !defined(_TITLE) + desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; +#endif + desc.pRootSignature = rootSignature; + + ComPtr pso; + ThrowIfFailed(device->CreateComputePipelineState(&desc, IID_GRAPHICS_PPV_ARGS(pso.GetAddressOf()))); + + SetDebugObjectName(pso.Get(), L"GenerateMips PSO"); + + return pso; + } + }; +} // anonymous namespace + +class ResourceUploadBatch::Impl +{ +public: + Impl( + _In_ ID3D12Device* device) + : mDevice(device) + , mInBeginEndBlock(false) + { + } + + // Call this before your multiple calls to Upload. + void Begin() + { + if (mInBeginEndBlock) + throw std::exception("Can't Begin: already in a Begin-End block."); + + ThrowIfFailed(mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(mCmdAlloc.ReleaseAndGetAddressOf()))); + ThrowIfFailed(mDevice->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAlloc.Get(), nullptr, IID_GRAPHICS_PPV_ARGS(mList.ReleaseAndGetAddressOf()))); + + PIXBeginEvent(mList.Get(), 0, __FUNCTIONW__); + + mInBeginEndBlock = true; + } + + // Asynchronously uploads a resource. The memory in subRes is copied. + // The resource must be in the COPY_DEST state. + void Upload( + _In_ ID3D12Resource* resource, + _In_ uint32_t subresourceIndexStart, + _In_reads_(numSubresources) D3D12_SUBRESOURCE_DATA* subRes, + _In_ uint32_t numSubresources) + { + if (!mInBeginEndBlock) + throw std::exception("Can't call Upload on a closed ResourceUploadBatch."); + + PIXBeginEvent(mList.Get(), 0, __FUNCTIONW__); + + UINT64 uploadSize = GetRequiredIntermediateSize( + resource, + subresourceIndexStart, + numSubresources); + + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC resDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadSize); + + // Create a temporary buffer + ComPtr scratchResource = nullptr; + ThrowIfFailed(mDevice->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &resDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, // D3D12_CLEAR_VALUE* pOptimizedClearValue + IID_GRAPHICS_PPV_ARGS(scratchResource.GetAddressOf()))); + + SetDebugObjectName(scratchResource.Get(), L"ResourceUploadBatch Temporary"); + + // Transition the resource to a copy target, copy and transition back + UpdateSubresources(mList.Get(), resource, scratchResource.Get(), 0, subresourceIndexStart, numSubresources, subRes); + + // Remember this upload object for delayed release + mTrackedObjects.push_back(scratchResource); + + PIXEndEvent(mList.Get()); + } + + // Asynchronously generate mips from a resource. + // Resource must be in the PIXEL_SHADER_RESOURCE state + void GenerateMips( + _In_ ID3D12Resource* resource) + { + if (resource == nullptr) + { + throw std::invalid_argument("Nullptr passed to GenerateMips"); + } + + ScopedPixEvent pix(mList.Get(), 0, __FUNCTIONW__); + + const auto& desc = resource->GetDesc(); + + if (desc.MipLevels == 1) + { + // Nothing to do + return; + } + if (desc.MipLevels == 0) + { + throw std::exception("GenerateMips: texture has no mips"); + } + if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) + { + throw std::exception("GenerateMips only supports Texture2D resources"); + } + if (desc.DepthOrArraySize != 1) + { + throw std::exception("GenerateMips only supports 2D textures of array size 1"); + } + + // Ensure that we have valid generate mips data + if (mGenMipsResources == nullptr) + { + mGenMipsResources = std::make_unique(mDevice.Get()); + } + + // Create a staging resource if we have to + ComPtr staging; + if ((desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) == 0) + { + D3D12_RESOURCE_DESC stagingDesc = desc; + stagingDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + ThrowIfFailed(mDevice->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &stagingDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(staging.GetAddressOf()))); + + SetDebugObjectName(staging.Get(), L"GenerateMips Staging"); + + // Copy the resource to staging + Transition(resource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE); + mList->CopyResource(staging.Get(), resource); + Transition(staging.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + } + else + { + // Resource is already a UAV so we can do this in-place + staging = resource; + } + + // Create a descriptor heap that holds our resource descriptors + ComPtr descriptorHeap; + D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {}; + descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + descriptorHeapDesc.NumDescriptors = desc.MipLevels; + mDevice->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(descriptorHeap.GetAddressOf())); + + uint32_t descriptorSize = mDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + // Create the top-level SRV + CD3DX12_CPU_DESCRIPTOR_HANDLE handleIt(descriptorHeap->GetCPUDescriptorHandleForHeapStart()); + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = desc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + + mDevice->CreateShaderResourceView(staging.Get(), &srvDesc, handleIt); + + // Create the UAVs for the tail + for (uint16_t mip = 1; mip < desc.MipLevels; ++mip) + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = ConvertSRVtoUAVFormat(desc.Format); + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = mip; + + handleIt.Offset(descriptorSize); + mDevice->CreateUnorderedAccessView(staging.Get(), nullptr, &uavDesc, handleIt); + } + + // Set up UAV barrier (used in loop) + D3D12_RESOURCE_BARRIER barrierUAV = {}; + barrierUAV.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrierUAV.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrierUAV.UAV.pResource = staging.Get(); + + // Barrier for transitioning the subresources to UAVs + D3D12_RESOURCE_BARRIER srv2uavDesc = {}; + srv2uavDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + srv2uavDesc.Transition.pResource = staging.Get(); + srv2uavDesc.Transition.Subresource = 0; + srv2uavDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + srv2uavDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + + // Barrier for transitioning the subresources to SRVs + D3D12_RESOURCE_BARRIER uav2srvDesc = {}; + uav2srvDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + uav2srvDesc.Transition.pResource = staging.Get(); + uav2srvDesc.Transition.Subresource = 0; + uav2srvDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + uav2srvDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + + // based on format, select srgb or not + ComPtr pso = mGenMipsResources->generateMipsPSO; + + // Set up state + mList->SetComputeRootSignature(mGenMipsResources->rootSignature.Get()); + mList->SetPipelineState(pso.Get()); + mList->SetDescriptorHeaps(1, descriptorHeap.GetAddressOf()); + mList->SetComputeRootDescriptorTable(GenerateMipsResources::SourceTexture, descriptorHeap->GetGPUDescriptorHandleForHeapStart()); + + // Get the descriptor handle -- uavH will increment over each loop + CD3DX12_GPU_DESCRIPTOR_HANDLE uavH( + descriptorHeap->GetGPUDescriptorHandleForHeapStart(), + descriptorSize); // offset by 1 descriptor + + // Process each mip + uint32_t mipWidth = (uint32_t)desc.Width; + uint32_t mipHeight = desc.Height; + for (uint32_t mip = 1; mip < desc.MipLevels; ++mip) + { + mipWidth = std::max(1, mipWidth >> 1); + mipHeight = std::max(1, mipHeight >> 1); + + // Transition the mip to a UAV + srv2uavDesc.Transition.Subresource = mip; + mList->ResourceBarrier(1, &srv2uavDesc); + + // Bind the mip subresources + mList->SetComputeRootDescriptorTable(GenerateMipsResources::TargetTexture, uavH); + + // Set constants + GenerateMipsResources::ConstantData constants; + constants.SrcMipIndex = mip - 1; + constants.InvOutTexelSize = XMFLOAT2(1 / (float)mipWidth, 1 / (float)mipHeight); + mList->SetComputeRoot32BitConstants( + GenerateMipsResources::Constants, + GenerateMipsResources::Num32BitConstants, + &constants, + 0); + + // Process this mip + mList->Dispatch( + (mipWidth + GenerateMipsResources::ThreadGroupSize - 1) / GenerateMipsResources::ThreadGroupSize, + (mipHeight + GenerateMipsResources::ThreadGroupSize - 1) / GenerateMipsResources::ThreadGroupSize, + 1); + + mList->ResourceBarrier(1, &barrierUAV); + + // Transition the mip to an SRV + uav2srvDesc.Transition.Subresource = mip; + mList->ResourceBarrier(1, &uav2srvDesc); + + // Offset the descriptor heap handles + uavH.Offset(descriptorSize); + } + + // If the staging resource is NOT the same as the resource, we need to copy everything back + if (staging.Get() != resource) + { + // Transition the resources ready for copy + Transition(staging.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE); + Transition(resource, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST); + + // Copy the entire resource back + mList->CopyResource(resource, staging.Get()); + + // Transition the target resource back to pixel shader resource + Transition(resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + mTrackedObjects.push_back(staging); + } + + // Add our temporary objects to the deferred deletion queue + mTrackedObjects.push_back(mGenMipsResources->rootSignature); + mTrackedObjects.push_back(pso); + mTrackedObjects.push_back(resource); + mTrackedObjects.push_back(descriptorHeap); + } + + // Transition a resource once you're done with it + void Transition( + _In_ ID3D12Resource* resource, + _In_ D3D12_RESOURCE_STATES stateBefore, + _In_ D3D12_RESOURCE_STATES stateAfter) + { + if (!mInBeginEndBlock) + throw std::exception("Can't call Upload on a closed ResourceUploadBatch."); + + TransitionResource(mList.Get(), resource, stateBefore, stateAfter); + } + + // Submits all the uploads to the driver. + // No more uploads can happen after this call until Begin is called again. + // This returns a handle to an event that can be waited on. + std::future End( + _In_ ID3D12CommandQueue* commandQueue) + { + if (!mInBeginEndBlock) + throw std::exception("ResourceUploadBatch already closed."); + + PIXEndEvent(mList.Get()); + + ThrowIfFailed(mList->Close()); + + // Submit the job to the GPU + commandQueue->ExecuteCommandLists(1, (ID3D12CommandList**)mList.GetAddressOf()); + + // Set an event so we get notified when the GPU has completed all its work + ComPtr fence; + ThrowIfFailed(mDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(fence.GetAddressOf()))); + HANDLE gpuCompletedEvent = CreateEventEx(nullptr, nullptr, 0, EVENT_ALL_ACCESS); + if (!gpuCompletedEvent) + throw std::exception("CreateEventEx"); + + ThrowIfFailed(commandQueue->Signal(fence.Get(), 1ULL)); + ThrowIfFailed(fence->SetEventOnCompletion(1ULL, gpuCompletedEvent)); + + // Create a packet of data that'll be passed to our waiting upload thread + UploadBatch* uploadBatch = new UploadBatch(); + uploadBatch->CommandList = mList; + uploadBatch->Fence = fence; + uploadBatch->GpuCompleteEvent = gpuCompletedEvent; + uploadBatch->TrackedObjects.insert(std::end(uploadBatch->TrackedObjects), std::begin(mTrackedObjects), std::end(mTrackedObjects)); + + // Kick off a thread that waits for the upload to complete on the GPU timeline. + // Let the thread run autonomously, but provide a future the user can wait on. + std::future future = std::async(std::launch::async, [uploadBatch]() + { + // Wait on the GPU-complete notification + auto wr = WaitForSingleObject(uploadBatch->GpuCompleteEvent, INFINITE); + assert(wr == WAIT_OBJECT_0); + wr; + + // Delete the batch + // Because the vector contains ComPtrs, their destructors will fire and the + // resources will be Released. + delete uploadBatch; + }); + + // Reset our state + mInBeginEndBlock = false; + mTrackedObjects.resize(0); + mList.Reset(); + mCmdAlloc.Reset(); + + return std::move(future); + } + +private: + struct UploadBatch + { + std::vector> TrackedObjects; + ComPtr CommandList; + ComPtr Fence; + HANDLE GpuCompleteEvent; + }; + + ComPtr mDevice; + ComPtr mCmdAlloc; + ComPtr mList; + std::unique_ptr mGenMipsResources; + + std::vector> mTrackedObjects; + bool mInBeginEndBlock; +}; + + + +// Public constructor. +ResourceUploadBatch::ResourceUploadBatch(_In_ ID3D12Device* device) + : pImpl(std::make_unique(device)) +{ +} + + +// Public destructor. +ResourceUploadBatch::~ResourceUploadBatch() +{ +} + + +// Move constructor. +ResourceUploadBatch::ResourceUploadBatch(ResourceUploadBatch&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +ResourceUploadBatch& ResourceUploadBatch::operator= (ResourceUploadBatch&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +void ResourceUploadBatch::Begin() +{ + pImpl->Begin(); +} + + +void ResourceUploadBatch::Upload( + _In_ ID3D12Resource* resource, + _In_ uint32_t subresourceIndexStart, + _In_reads_(numSubresources) D3D12_SUBRESOURCE_DATA* subRes, + _In_ uint32_t numSubresources) +{ + pImpl->Upload(resource, subresourceIndexStart, subRes, numSubresources); +} + + +void ResourceUploadBatch::GenerateMips(_In_ ID3D12Resource* resource) +{ + pImpl->GenerateMips(resource); +} + + +void ResourceUploadBatch::Transition( + _In_ ID3D12Resource* resource, + _In_ D3D12_RESOURCE_STATES stateBefore, + _In_ D3D12_RESOURCE_STATES stateAfter) +{ + pImpl->Transition(resource, stateBefore, stateAfter); +} + + +std::future ResourceUploadBatch::End(_In_ ID3D12CommandQueue* commandQueue) +{ + return std::move(pImpl->End(commandQueue)); +} + diff --git a/Kits/DirectXTK12/Src/SDKMesh.h b/Kits/DirectXTK12/Src/SDKMesh.h new file mode 100644 index 00000000..6848d9e5 --- /dev/null +++ b/Kits/DirectXTK12/Src/SDKMesh.h @@ -0,0 +1,340 @@ +//-------------------------------------------------------------------------------------- +// File: SDKMesh.h +// +// SDKMESH format is generated by the legacy DirectX SDK's Content Exporter and +// originally rendered by the DXUT helper class SDKMesh +// +// http://go.microsoft.com/fwlink/?LinkId=226208 +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + + +namespace DXUT +{ + // .SDKMESH files + + // SDKMESH_HEADER + // SDKMESH_VERTEX_BUFFER_HEADER header->VertexStreamHeadersOffset + // SDKMESH_INDEX_BUFFER_HEADER header->IndexStreamHeadersOffset + // SDKMESH_MESH header->MeshDataOffset + // SDKMESH_SUBSET header->SubsetDataOffset + // SDKMESH_FRAME header->FrameDataOffset + // SDKMESH_MATERIAL header->MaterialDataOffset + // [header->NonBufferDataSize] + // { [ header->NumVertexBuffers] + // VB data + // } + // { [ header->NumIndexBuffers] + // IB data + // } + + + // .SDDKANIM files + + // SDKANIMATION_FILE_HEADER + // uint8_t[] - Length of fileheader->AnimationDataSize + + // .SDKMESH uses Direct3D 9 decls, but only a subset of these is ever generated by the legacy DirectX SDK Content Exporter + + // D3DDECLUSAGE_POSITION / D3DDECLTYPE_FLOAT3 + // (D3DDECLUSAGE_BLENDWEIGHT / D3DDECLTYPE_UBYTE4N + // D3DDECLUSAGE_BLENDINDICES / D3DDECLTYPE_UBYTE4)? + // (D3DDECLUSAGE_NORMAL / D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_UBYTE4N, or D3DDECLTYPE_DEC3N [not supported])? + // (D3DDECLUSAGE_COLOR / D3DDECLTYPE_D3DCOLOR)? + // (D3DDECLUSAGE_TEXCOORD / D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2 or D3DDECLTYPE_FLOAT16_2, D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_FLOAT4 or D3DDECLTYPE_FLOAT16_4)* + // (D3DDECLUSAGE_TANGENT / same as D3DDECLUSAGE_NORMAL)? + // (D3DDECLUSAGE_BINORMAL / same as D3DDECLUSAGE_NORMAL)? + + enum D3DDECLUSAGE + { + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT =1, + D3DDECLUSAGE_BLENDINDICES =2, + D3DDECLUSAGE_NORMAL =3, + D3DDECLUSAGE_TEXCOORD = 5, + D3DDECLUSAGE_TANGENT = 6, + D3DDECLUSAGE_BINORMAL = 7, + D3DDECLUSAGE_COLOR = 10, + }; + + enum D3DDECLTYPE + { + D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) + D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) + D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) + D3DDECLTYPE_FLOAT4 = 3, // 4D float + D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range + // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) + D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned uint8_t + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + // Note: There is no equivalent to D3DDECLTYPE_DEC3N (14) as a DXGI_FORMAT + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. + }; + + #pragma pack(push,4) + + struct D3DVERTEXELEMENT9 + { + uint16_t Stream; // Stream index + uint16_t Offset; // Offset in the stream in bytes + uint8_t Type; // Data type + uint8_t Method; // Processing method + uint8_t Usage; // Semantics + uint8_t UsageIndex; // Semantic index + }; + + #pragma pack(pop) + + //-------------------------------------------------------------------------------------- + // Hard Defines for the various structures + //-------------------------------------------------------------------------------------- + const uint32_t SDKMESH_FILE_VERSION = 101; + const uint32_t MAX_VERTEX_ELEMENTS = 32; + const uint32_t MAX_VERTEX_STREAMS = 16; + const uint32_t MAX_FRAME_NAME = 100; + const uint32_t MAX_MESH_NAME = 100; + const uint32_t MAX_SUBSET_NAME = 100; + const uint32_t MAX_MATERIAL_NAME = 100; + const uint32_t MAX_TEXTURE_NAME = MAX_PATH; + const uint32_t MAX_MATERIAL_PATH = MAX_PATH; + const uint32_t INVALID_FRAME = uint32_t(-1); + const uint32_t INVALID_MESH = uint32_t(-1); + const uint32_t INVALID_MATERIAL = uint32_t(-1); + const uint32_t INVALID_SUBSET = uint32_t(-1); + const uint32_t INVALID_ANIMATION_DATA = uint32_t(-1); + const uint32_t INVALID_SAMPLER_SLOT = uint32_t(-1); + const uint32_t ERROR_RESOURCE_VALUE = 1; + + //-------------------------------------------------------------------------------------- + // Enumerated Types. + //-------------------------------------------------------------------------------------- + enum SDKMESH_PRIMITIVE_TYPE + { + PT_TRIANGLE_LIST = 0, + PT_TRIANGLE_STRIP, + PT_LINE_LIST, + PT_LINE_STRIP, + PT_POINT_LIST, + PT_TRIANGLE_LIST_ADJ, + PT_TRIANGLE_STRIP_ADJ, + PT_LINE_LIST_ADJ, + PT_LINE_STRIP_ADJ, + PT_QUAD_PATCH_LIST, + PT_TRIANGLE_PATCH_LIST, + }; + + enum SDKMESH_INDEX_TYPE + { + IT_16BIT = 0, + IT_32BIT, + }; + + enum FRAME_TRANSFORM_TYPE + { + FTT_RELATIVE = 0, + FTT_ABSOLUTE, //This is not currently used but is here to support absolute transformations in the future + }; + + //-------------------------------------------------------------------------------------- + // Structures. + //-------------------------------------------------------------------------------------- + #pragma pack(push,8) + + struct SDKMESH_HEADER + { + //Basic Info and sizes + uint32_t Version; + uint8_t IsBigEndian; + uint64_t HeaderSize; + uint64_t NonBufferDataSize; + uint64_t BufferDataSize; + + //Stats + uint32_t NumVertexBuffers; + uint32_t NumIndexBuffers; + uint32_t NumMeshes; + uint32_t NumTotalSubsets; + uint32_t NumFrames; + uint32_t NumMaterials; + + //Offsets to Data + uint64_t VertexStreamHeadersOffset; + uint64_t IndexStreamHeadersOffset; + uint64_t MeshDataOffset; + uint64_t SubsetDataOffset; + uint64_t FrameDataOffset; + uint64_t MaterialDataOffset; + }; + + struct SDKMESH_VERTEX_BUFFER_HEADER + { + uint64_t NumVertices; + uint64_t SizeBytes; + uint64_t StrideBytes; + D3DVERTEXELEMENT9 Decl[MAX_VERTEX_ELEMENTS]; + union + { + uint64_t DataOffset; + }; + }; + + struct SDKMESH_INDEX_BUFFER_HEADER + { + uint64_t NumIndices; + uint64_t SizeBytes; + uint32_t IndexType; + union + { + uint64_t DataOffset; + }; + }; + + struct SDKMESH_MESH + { + char Name[MAX_MESH_NAME]; + uint8_t NumVertexBuffers; + uint32_t VertexBuffers[MAX_VERTEX_STREAMS]; + uint32_t IndexBuffer; + uint32_t NumSubsets; + uint32_t NumFrameInfluences; //aka bones + + DirectX::XMFLOAT3 BoundingBoxCenter; + DirectX::XMFLOAT3 BoundingBoxExtents; + + union + { + uint64_t SubsetOffset; + INT* pSubsets; + }; + union + { + uint64_t FrameInfluenceOffset; + uint32_t* pFrameInfluences; + }; + }; + + struct SDKMESH_SUBSET + { + char Name[MAX_SUBSET_NAME]; + uint32_t MaterialID; + uint32_t PrimitiveType; + uint64_t IndexStart; + uint64_t IndexCount; + uint64_t VertexStart; + uint64_t VertexCount; + }; + + struct SDKMESH_FRAME + { + char Name[MAX_FRAME_NAME]; + uint32_t Mesh; + uint32_t ParentFrame; + uint32_t ChildFrame; + uint32_t SiblingFrame; + DirectX::XMFLOAT4X4 Matrix; + uint32_t AnimationDataIndex; //Used to index which set of keyframes transforms this frame + }; + + struct SDKMESH_MATERIAL + { + char Name[MAX_MATERIAL_NAME]; + + // Use MaterialInstancePath + char MaterialInstancePath[MAX_MATERIAL_PATH]; + + // Or fall back to d3d8-type materials + char DiffuseTexture[MAX_TEXTURE_NAME]; + char NormalTexture[MAX_TEXTURE_NAME]; + char SpecularTexture[MAX_TEXTURE_NAME]; + + DirectX::XMFLOAT4 Diffuse; + DirectX::XMFLOAT4 Ambient; + DirectX::XMFLOAT4 Specular; + DirectX::XMFLOAT4 Emissive; + float Power; + + union + { + uint64_t Force64_1; //Force the union to 64bits + }; + union + { + uint64_t Force64_2; //Force the union to 64bits + }; + union + { + uint64_t Force64_3; //Force the union to 64bits + }; + + union + { + uint64_t Force64_4; //Force the union to 64bits + }; + union + { + uint64_t Force64_5; //Force the union to 64bits + }; + union + { + uint64_t Force64_6; //Force the union to 64bits + }; + }; + + struct SDKANIMATION_FILE_HEADER + { + uint32_t Version; + uint8_t IsBigEndian; + uint32_t FrameTransformType; + uint32_t NumFrames; + uint32_t NumAnimationKeys; + uint32_t AnimationFPS; + uint64_t AnimationDataSize; + uint64_t AnimationDataOffset; + }; + + struct SDKANIMATION_DATA + { + DirectX::XMFLOAT3 Translation; + DirectX::XMFLOAT4 Orientation; + DirectX::XMFLOAT3 Scaling; + }; + + struct SDKANIMATION_FRAME_DATA + { + char FrameName[MAX_FRAME_NAME]; + union + { + uint64_t DataOffset; + SDKANIMATION_DATA* pAnimationData; + }; + }; + + #pragma pack(pop) + +} // namespace + +static_assert( sizeof(DXUT::D3DVERTEXELEMENT9) == 8, "Direct3D9 Decl structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_HEADER)== 104, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) == 288, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER) == 32, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_MESH) == 224, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_SUBSET) == 144, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_FRAME) == 184, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKMESH_MATERIAL) == 1256, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_FILE_HEADER) == 40, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_DATA) == 40, "SDK Mesh structure size incorrect" ); +static_assert( sizeof(DXUT::SDKANIMATION_FRAME_DATA) == 112, "SDK Mesh structure size incorrect" ); diff --git a/Kits/DirectXTK12/Src/ScreenGrab.cpp b/Kits/DirectXTK12/Src/ScreenGrab.cpp new file mode 100644 index 00000000..24045e74 --- /dev/null +++ b/Kits/DirectXTK12/Src/ScreenGrab.cpp @@ -0,0 +1,713 @@ +//-------------------------------------------------------------------------------------- +// File: ScreenGrab.cpp +// +// Function for capturing a 2D texture and saving it to a file (aka a 'screenshot' +// when used on a Direct3D Render Target). +// +// Note these functions are useful as a light-weight runtime screen grabber. For +// full-featured texture capture, DDS writer, and texture processing pipeline, +// see the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +// Does not capture 1D textures or 3D textures (volume maps) + +// Does not capture mipmap chains, only the top-most texture level is saved + +// For 2D array textures and cubemaps, it captures only the first image in the array + +#include "pch.h" + +#include "ScreenGrab.h" +#include "DirectXHelpers.h" + +#include "dds.h" +#include "PlatformHelpers.h" +#include "LoaderHelpers.h" + +using Microsoft::WRL::ComPtr; +using namespace DirectX; + +namespace +{ + //-------------------------------------------------------------------------------------- + HRESULT CaptureTexture(_In_ ID3D12Device* device, + _In_ ID3D12CommandQueue* pCommandQ, + _In_ ID3D12Resource* pSource, + _In_ UINT64 srcPitch, + _In_ const D3D12_RESOURCE_DESC& desc, + _Inout_ ComPtr& pStaging) + { + if (!pCommandQ || !pSource) + return E_INVALIDARG; + + if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + D3D12_HEAP_PROPERTIES sourceHeapProperties; + D3D12_HEAP_FLAGS sourceHeapFlags; + HRESULT hr = pSource->GetHeapProperties(&sourceHeapProperties, &sourceHeapFlags); + if (FAILED(hr)) + return hr; + + if (sourceHeapProperties.Type == D3D12_HEAP_TYPE_READBACK) + { + // Handle case where the source is already a staging texture we can use directly + pStaging = pSource; + return S_OK; + } + + // Create a command allocator + ComPtr commandAlloc; + hr = device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(commandAlloc.GetAddressOf())); + if (FAILED(hr)) + return hr; + + // Spin up a new command list + ComPtr commandList; + hr = device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAlloc.Get(), nullptr, IID_GRAPHICS_PPV_ARGS(commandList.GetAddressOf())); + if (FAILED(hr)) + return hr; + + // Create a fence + ComPtr fence; + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(fence.GetAddressOf())); + if (FAILED(hr)) + return hr; + + assert((srcPitch & 0xFF) == 0); + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + CD3DX12_HEAP_PROPERTIES readBackHeapProperties(D3D12_HEAP_TYPE_READBACK); + + // Readback resources must be buffers + D3D12_RESOURCE_DESC bufferDesc = {}; + bufferDesc.Alignment = desc.Alignment; + bufferDesc.DepthOrArraySize = 1; + bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + bufferDesc.Format = DXGI_FORMAT_UNKNOWN; + bufferDesc.Height = 1; + bufferDesc.Width = srcPitch * desc.Height; + bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + bufferDesc.MipLevels = 1; + bufferDesc.SampleDesc.Count = 1; + bufferDesc.SampleDesc.Quality = 0; + + ComPtr copySource(pSource); + if (desc.SampleDesc.Count > 1) + { + // MSAA content must be resolved before being copied to a staging texture + auto descCopy = desc; + descCopy.SampleDesc.Count = 1; + descCopy.SampleDesc.Quality = 0; + + ComPtr pTemp; + hr = device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &descCopy, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(pTemp.GetAddressOf())); + if (FAILED(hr)) + return hr; + + assert(pTemp); + + DXGI_FORMAT fmt = EnsureNotTypeless(desc.Format); + + D3D12_FEATURE_DATA_FORMAT_SUPPORT formatInfo = { fmt }; + hr = device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatInfo, sizeof(formatInfo)); + if (FAILED(hr)) + return hr; + + if (!(formatInfo.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) + return E_FAIL; + + for (UINT item = 0; item < desc.DepthOrArraySize; ++item) + { + for (UINT level = 0; level < desc.MipLevels; ++level) + { + UINT index = D3D12CalcSubresource(level, item, 0, desc.MipLevels, desc.DepthOrArraySize); + commandList->ResolveSubresource(pTemp.Get(), index, pSource, index, fmt); + } + } + + copySource = pTemp; + } + + // Create a staging texture + hr = device->CreateCommittedResource( + &readBackHeapProperties, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(pStaging.GetAddressOf())); + if (FAILED(hr)) + return hr; + + assert(pStaging); + + // Get the copy target location + D3D12_PLACED_SUBRESOURCE_FOOTPRINT bufferFootprint = {}; + bufferFootprint.Footprint.Width = (UINT)desc.Width; + bufferFootprint.Footprint.Height = desc.Height; + bufferFootprint.Footprint.Depth = 1; + bufferFootprint.Footprint.RowPitch = (UINT)(srcPitch); + bufferFootprint.Footprint.Format = desc.Format; + + CD3DX12_TEXTURE_COPY_LOCATION copyDest(pStaging.Get(), bufferFootprint); + CD3DX12_TEXTURE_COPY_LOCATION copySrc(copySource.Get(), 0); + + // Copy the texture + commandList->CopyTextureRegion(©Dest, 0, 0, 0, ©Src, nullptr); + + commandList->Close(); + + // Execute the command list + pCommandQ->ExecuteCommandLists(1, (ID3D12CommandList**)commandList.GetAddressOf()); + + // Signal the fence + pCommandQ->Signal(fence.Get(), 1); + + // Block until the copy is complete + while (fence->GetCompletedValue() < 1) + SwitchToThread(); + + return S_OK; + } +} // anonymous namespace + + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ, + ID3D12Resource* pSource, + const wchar_t* fileName ) +{ + if ( !fileName ) + return E_INVALIDARG; + + ComPtr device; + pCommandQ->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); + + // Get the size of the image + D3D12_RESOURCE_DESC desc = pSource->GetDesc(); + UINT64 totalResourceSize = 0; + UINT64 fpRowPitch = 0; + UINT fpRowCount = 0; + // Get the rowcount, pitch and size of the top mip + device->GetCopyableFootprints( + &desc, + 0, + 1, + 0, + nullptr, + &fpRowCount, + &fpRowPitch, + &totalResourceSize); + + // Round up the srcPitch to multiples of 256 + UINT64 dstRowPitch = (fpRowPitch + 255) & ~0xFF; + + ComPtr pStaging; + HRESULT hr = CaptureTexture( device.Get(), pCommandQ, pSource, dstRowPitch, desc, pStaging ); + if ( FAILED(hr) ) + return hr; + + // Create file +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) + ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) ); +#else + ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) ); +#endif + if ( !hFile ) + return HRESULT_FROM_WIN32( GetLastError() ); + + auto_delete_file delonfail(hFile.get()); + + // Setup header + const size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); + uint8_t fileHeader[ MAX_HEADER_SIZE ]; + + *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; + + auto header = reinterpret_cast( &fileHeader[0] + sizeof(uint32_t) ); + size_t headerSize = sizeof(uint32_t) + sizeof(DDS_HEADER); + memset( header, 0, sizeof(DDS_HEADER) ); + header->size = sizeof( DDS_HEADER ); + header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; + header->height = desc.Height; + header->width = (uint32_t) desc.Width; + header->mipMapCount = 1; + header->caps = DDS_SURFACE_FLAGS_TEXTURE; + + // Try to use a legacy .DDS pixel format for better tools support, otherwise fallback to 'DX10' header extension + DDS_HEADER_DXT10* extHeader = nullptr; + switch( desc.Format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8B8G8R8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R16G16_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_G16R16, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R8G8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8L8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R16_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_L16, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_L8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC1_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC2_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT3, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC3_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DXT5, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC4_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC4_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC5_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_BC5_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_BC5_SNORM, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_B5G6R5_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_R5G6B5, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A1R5G5B5, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R8G8_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_V8U8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R8G8B8A8_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_Q8W8V8U8, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_R16G16_SNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_V16U16, sizeof(DDS_PIXELFORMAT) ); break; + case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1 + case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1 + case DXGI_FORMAT_YUY2: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2 + case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2 + + // Legacy D3DX formats using D3DFMT enum value as FourCC + case DXGI_FORMAT_R32G32B32A32_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 116; break; // D3DFMT_A32B32G32R32F + case DXGI_FORMAT_R16G16B16A16_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 113; break; // D3DFMT_A16B16G16R16F + case DXGI_FORMAT_R16G16B16A16_UNORM: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 36; break; // D3DFMT_A16B16G16R16 + case DXGI_FORMAT_R16G16B16A16_SNORM: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 110; break; // D3DFMT_Q16W16V16U16 + case DXGI_FORMAT_R32G32_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 115; break; // D3DFMT_G32R32F + case DXGI_FORMAT_R16G16_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 112; break; // D3DFMT_G16R16F + case DXGI_FORMAT_R32_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 114; break; // D3DFMT_R32F + case DXGI_FORMAT_R16_FLOAT: header->ddspf.size = sizeof(DDS_PIXELFORMAT); header->ddspf.flags = DDS_FOURCC; header->ddspf.fourCC = 111; break; // D3DFMT_R16F + + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + + default: + memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT) ); + + headerSize += sizeof(DDS_HEADER_DXT10); + extHeader = reinterpret_cast( reinterpret_cast(&fileHeader[0]) + sizeof(uint32_t) + sizeof(DDS_HEADER) ); + memset( extHeader, 0, sizeof(DDS_HEADER_DXT10) ); + extHeader->dxgiFormat = desc.Format; + extHeader->resourceDimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + extHeader->arraySize = 1; + break; + } + + size_t rowPitch, slicePitch, rowCount; + GetSurfaceInfo( (size_t)desc.Width, desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount ); + + if ( IsCompressed( desc.Format ) ) + { + header->flags |= DDS_HEADER_FLAGS_LINEARSIZE; + header->pitchOrLinearSize = static_cast( slicePitch ); + } + else + { + header->flags |= DDS_HEADER_FLAGS_PITCH; + header->pitchOrLinearSize = static_cast( rowPitch ); + } + + // Setup pixels + std::unique_ptr pixels( new (std::nothrow) uint8_t[ slicePitch ] ); + if (!pixels) + return E_OUTOFMEMORY; + + assert(fpRowCount == rowCount); + assert(fpRowPitch == rowPitch); + + void* pMappedMemory; + D3D12_RANGE readRange = { 0, static_cast(dstRowPitch * rowCount) }; + D3D12_RANGE writeRange = { 0, 0 }; + hr = pStaging->Map(0, &readRange, &pMappedMemory ); + if ( FAILED(hr) ) + return hr; + + auto sptr = reinterpret_cast(pMappedMemory); + if ( !sptr ) + { + pStaging->Unmap(0, &writeRange); + return E_POINTER; + } + + uint8_t* dptr = pixels.get(); + + size_t msize = std::min( rowPitch, rowPitch ); + for( size_t h = 0; h < rowCount; ++h ) + { + memcpy_s( dptr, rowPitch, sptr, msize ); + sptr += dstRowPitch; + dptr += rowPitch; + } + + pStaging->Unmap( 0, &writeRange ); + + // Write header & pixels + DWORD bytesWritten; + if ( !WriteFile( hFile.get(), fileHeader, static_cast( headerSize ), &bytesWritten, 0 ) ) + return HRESULT_FROM_WIN32( GetLastError() ); + + if ( bytesWritten != headerSize ) + return E_FAIL; + + if ( !WriteFile( hFile.get(), pixels.get(), static_cast( slicePitch ), &bytesWritten, 0 ) ) + return HRESULT_FROM_WIN32( GetLastError() ); + + if ( bytesWritten != slicePitch ) + return E_FAIL; + + delonfail.clear(); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +namespace DirectX +{ +extern IWICImagingFactory2* _GetWIC(); +} + +_Use_decl_annotations_ +HRESULT DirectX::SaveWICTextureToFile( ID3D12CommandQueue* pCommandQ, + ID3D12Resource* pSource, + REFGUID guidContainerFormat, + const wchar_t* fileName, + const GUID* targetFormat, + std::function setCustomProps ) +{ + if ( !fileName ) + return E_INVALIDARG; + + ComPtr device; + pCommandQ->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())); + + // Get the size of the image + D3D12_RESOURCE_DESC desc = pSource->GetDesc(); + UINT64 totalResourceSize = 0; + UINT64 fpRowPitch = 0; + UINT fpRowCount = 0; + // Get the rowcount, pitch and size of the top mip + device->GetCopyableFootprints( + &desc, + 0, + 1, + 0, + nullptr, + &fpRowCount, + &fpRowPitch, + &totalResourceSize); + + // Round up the srcPitch to multiples of 256 + UINT64 dstRowPitch = (fpRowPitch + 255) & ~0xFF; + + ComPtr pStaging; + HRESULT hr = CaptureTexture(device.Get(), pCommandQ, pSource, dstRowPitch, desc, pStaging); + if (FAILED(hr)) + return hr; + + // Determine source format's WIC equivalent + WICPixelFormatGUID pfGuid; + bool sRGB = false; + switch ( desc.Format ) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: pfGuid = GUID_WICPixelFormat128bppRGBAFloat; break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: pfGuid = GUID_WICPixelFormat64bppRGBAHalf; break; + case DXGI_FORMAT_R16G16B16A16_UNORM: pfGuid = GUID_WICPixelFormat64bppRGBA; break; + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: pfGuid = GUID_WICPixelFormat32bppRGBA1010102XR; break; // DXGI 1.1 + case DXGI_FORMAT_R10G10B10A2_UNORM: pfGuid = GUID_WICPixelFormat32bppRGBA1010102; break; + case DXGI_FORMAT_B5G5R5A1_UNORM: pfGuid = GUID_WICPixelFormat16bppBGRA5551; break; + case DXGI_FORMAT_B5G6R5_UNORM: pfGuid = GUID_WICPixelFormat16bppBGR565; break; + case DXGI_FORMAT_R32_FLOAT: pfGuid = GUID_WICPixelFormat32bppGrayFloat; break; + case DXGI_FORMAT_R16_FLOAT: pfGuid = GUID_WICPixelFormat16bppGrayHalf; break; + case DXGI_FORMAT_R16_UNORM: pfGuid = GUID_WICPixelFormat16bppGray; break; + case DXGI_FORMAT_R8_UNORM: pfGuid = GUID_WICPixelFormat8bppGray; break; + case DXGI_FORMAT_A8_UNORM: pfGuid = GUID_WICPixelFormat8bppAlpha; break; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + pfGuid = GUID_WICPixelFormat32bppRGBA; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + pfGuid = GUID_WICPixelFormat32bppRGBA; + sRGB = true; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: // DXGI 1.1 + pfGuid = GUID_WICPixelFormat32bppBGRA; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: // DXGI 1.1 + pfGuid = GUID_WICPixelFormat32bppBGRA; + sRGB = true; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM: // DXGI 1.1 + pfGuid = GUID_WICPixelFormat32bppBGR; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: // DXGI 1.1 + pfGuid = GUID_WICPixelFormat32bppBGR; + sRGB = true; + break; + + default: + return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); + } + + auto pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + ComPtr stream; + hr = pWIC->CreateStream( stream.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = stream->InitializeFromFilename( fileName, GENERIC_WRITE ); + if ( FAILED(hr) ) + return hr; + + auto_delete_file_wic delonfail(stream, fileName); + + ComPtr encoder; + hr = pWIC->CreateEncoder( guidContainerFormat, 0, encoder.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = encoder->Initialize( stream.Get(), WICBitmapEncoderNoCache ); + if ( FAILED(hr) ) + return hr; + + ComPtr frame; + ComPtr props; + hr = encoder->CreateNewFrame( frame.GetAddressOf(), props.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + if ( targetFormat && memcmp( &guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 ) + { + // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel + PROPBAG2 option = {}; + option.pstrName = L"EnableV5Header32bppBGRA"; + + VARIANT varValue; + varValue.vt = VT_BOOL; + varValue.boolVal = VARIANT_TRUE; + (void)props->Write( 1, &option, &varValue ); + } + + if ( setCustomProps ) + { + setCustomProps( props.Get() ); + } + + hr = frame->Initialize( props.Get() ); + if ( FAILED(hr) ) + return hr; + + hr = frame->SetSize( (UINT)desc.Width, desc.Height ); + if ( FAILED(hr) ) + return hr; + + hr = frame->SetResolution( 72, 72 ); + if ( FAILED(hr) ) + return hr; + + // Pick a target format + WICPixelFormatGUID targetGuid; + if ( targetFormat ) + { + targetGuid = *targetFormat; + } + else + { + // Screenshots don’t typically include the alpha channel of the render target + switch ( desc.Format ) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + targetGuid = GUID_WICPixelFormat96bppRGBFloat; // WIC 2 + break; + + case DXGI_FORMAT_R16G16B16A16_UNORM: targetGuid = GUID_WICPixelFormat48bppBGR; break; + case DXGI_FORMAT_B5G5R5A1_UNORM: targetGuid = GUID_WICPixelFormat16bppBGR555; break; + case DXGI_FORMAT_B5G6R5_UNORM: targetGuid = GUID_WICPixelFormat16bppBGR565; break; + + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_A8_UNORM: + targetGuid = GUID_WICPixelFormat8bppGray; + break; + + default: + targetGuid = GUID_WICPixelFormat24bppBGR; + break; + } + } + + hr = frame->SetPixelFormat( &targetGuid ); + if ( FAILED(hr) ) + return hr; + + if ( targetFormat && memcmp( targetFormat, &targetGuid, sizeof(WICPixelFormatGUID) ) != 0 ) + { + // Requested output pixel format is not supported by the WIC codec + return E_FAIL; + } + + // Encode WIC metadata + ComPtr metawriter; + if ( SUCCEEDED( frame->GetMetadataQueryWriter( metawriter.GetAddressOf() ) ) ) + { + PROPVARIANT value; + PropVariantInit( &value ); + + value.vt = VT_LPSTR; + value.pszVal = "DirectXTK"; + + if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 ) + { + // Set Software name + (void)metawriter->SetMetadataByName( L"/tEXt/{str=Software}", &value ); + + // Set sRGB chunk + if ( sRGB ) + { + value.vt = VT_UI1; + value.bVal = 0; + (void)metawriter->SetMetadataByName( L"/sRGB/RenderingIntent", &value ); + } + } +#if defined(_XBOX_ONE) && defined(_TITLE) + else if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID) ) == 0 ) + { + // Set Software name + (void)metawriter->SetMetadataByName( L"/app1/ifd/{ushort=305}", &value ); + + if ( sRGB ) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName( L"/app1/ifd/exif/{ushort=40961}", &value ); + } + } + else if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID) ) == 0 ) + { + // Set Software name + (void)metawriter->SetMetadataByName( L"/ifd/{ushort=305}", &value ); + + if ( sRGB ) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName( L"/ifd/exif/{ushort=40961}", &value ); + } + } +#else + else + { + // Set Software name + (void)metawriter->SetMetadataByName( L"System.ApplicationName", &value ); + + if ( sRGB ) + { + // Set EXIF Colorspace of sRGB + value.vt = VT_UI2; + value.uiVal = 1; + (void)metawriter->SetMetadataByName( L"System.Image.ColorSpace", &value ); + } + } +#endif + } + + void* pMappedMemory; + D3D12_RANGE readRange = {0, static_cast(dstRowPitch * desc.Height)}; + D3D12_RANGE writeRange = {0, 0}; + hr = pStaging->Map(0, &readRange, &pMappedMemory); + if (FAILED(hr)) + return hr; + + if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 ) + { + // Conversion required to write + ComPtr source; + hr = pWIC->CreateBitmapFromMemory((UINT) desc.Width, desc.Height, pfGuid, + (UINT) dstRowPitch, (UINT) dstRowPitch * desc.Height, + reinterpret_cast(pMappedMemory), source.GetAddressOf() ); + if ( FAILED(hr) ) + { + pStaging->Unmap( 0, &writeRange ); + return hr; + } + + ComPtr FC; + hr = pWIC->CreateFormatConverter( FC.GetAddressOf() ); + if ( FAILED(hr) ) + { + pStaging->Unmap(0, &writeRange); + return hr; + } + + BOOL canConvert = FALSE; + hr = FC->CanConvert( pfGuid, targetGuid, &canConvert ); + if ( FAILED(hr) || !canConvert ) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize( source.Get(), targetGuid, WICBitmapDitherTypeNone, 0, 0, WICBitmapPaletteTypeCustom ); + if ( FAILED(hr) ) + { + pStaging->Unmap(0, &writeRange); + return hr; + } + + WICRect rect = { 0, 0, static_cast( desc.Width ), static_cast( desc.Height ) }; + hr = frame->WriteSource( FC.Get(), &rect ); + if ( FAILED(hr) ) + { + pStaging->Unmap(0, &writeRange); + return hr; + } + } + else + { + // No conversion required + hr = frame->WritePixels( desc.Height, (UINT) dstRowPitch, (UINT) dstRowPitch * desc.Height, reinterpret_cast( pMappedMemory ) ); + if ( FAILED(hr) ) + return hr; + } + + pStaging->Unmap(0, &writeRange); + + hr = frame->Commit(); + if ( FAILED(hr) ) + return hr; + + hr = encoder->Commit(); + if ( FAILED(hr) ) + return hr; + + delonfail.clear(); + + return S_OK; +} diff --git a/Kits/DirectXTK12/Src/Shaders/AlphaTestEffect.fx b/Kits/DirectXTK12/Src/Shaders/AlphaTestEffect.fx new file mode 100644 index 00000000..d6aee2e0 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/AlphaTestEffect.fx @@ -0,0 +1,140 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +Texture2D Texture : register(t0); +sampler Sampler : register(s0); + + +cbuffer Parameters : register(b0) +{ + float4 DiffuseColor : packoffset(c0); + float4 AlphaTest : packoffset(c1); + float3 FogColor : packoffset(c2); + float4 FogVector : packoffset(c3); + float4x4 WorldViewProj : packoffset(c4); +}; + +#include "Structures.fxh" +#include "Common.fxh" +#include "RootSig.fxh" + +// Vertex shader: basic. +[RootSignature(MainRS)] +VSOutputTx VSAlphaTest(VSInputTx vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: no fog. +[RootSignature(MainRS)] +VSOutputTxNoFog VSAlphaTestNoFog(VSInputTx vin) +{ + VSOutputTxNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: vertex color. +[RootSignature(MainRS)] +VSOutputTx VSAlphaTestVc(VSInputTxVc vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: vertex color, no fog. +[RootSignature(MainRS)] +VSOutputTxNoFog VSAlphaTestVcNoFog(VSInputTxVc vin) +{ + VSOutputTxNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Pixel shader: less/greater compare function. +[RootSignature(MainRS)] +float4 PSAlphaTestLtGt(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + clip((color.a < AlphaTest.x) ? AlphaTest.z : AlphaTest.w); + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: less/greater compare function, no fog. +[RootSignature(MainRS)] +float4 PSAlphaTestLtGtNoFog(PSInputTxNoFog pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + clip((color.a < AlphaTest.x) ? AlphaTest.z : AlphaTest.w); + + return color; +} + + +// Pixel shader: equal/notequal compare function. +[RootSignature(MainRS)] +float4 PSAlphaTestEqNe(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + clip((abs(color.a - AlphaTest.x) < AlphaTest.y) ? AlphaTest.z : AlphaTest.w); + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: equal/notequal compare function, no fog. +[RootSignature(MainRS)] +float4 PSAlphaTestEqNeNoFog(PSInputTxNoFog pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + clip((abs(color.a - AlphaTest.x) < AlphaTest.y) ? AlphaTest.z : AlphaTest.w); + + return color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/BasicEffect.fx b/Kits/DirectXTK12/Src/Shaders/BasicEffect.fx new file mode 100644 index 00000000..e9d7ffd9 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/BasicEffect.fx @@ -0,0 +1,471 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +Texture2D Texture : register(t0); +sampler Sampler : register(s0); + + +cbuffer Parameters : register(b0) +{ + float4 DiffuseColor : packoffset(c0); + float3 EmissiveColor : packoffset(c1); + float3 SpecularColor : packoffset(c2); + float SpecularPower : packoffset(c2.w); + + float3 LightDirection[3] : packoffset(c3); + float3 LightDiffuseColor[3] : packoffset(c6); + float3 LightSpecularColor[3] : packoffset(c9); + + float3 EyePosition : packoffset(c12); + + float3 FogColor : packoffset(c13); + float4 FogVector : packoffset(c14); + + float4x4 World : packoffset(c15); + float3x3 WorldInverseTranspose : packoffset(c19); + float4x4 WorldViewProj : packoffset(c22); +}; + + +#include "Structures.fxh" +#include "Common.fxh" +#include "RootSig.fxh" +#include "Lighting.fxh" + + +// Vertex shader: basic. +[RootSignature(MainRS)] +VSOutput VSBasic(VSInput vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + return vout; +} + + +// Vertex shader: no fog. +[RootSignature(MainRS)] +VSOutputNoFog VSBasicNoFog(VSInput vin) +{ + VSOutputNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + return vout; +} + + +// Vertex shader: vertex color. +[RootSignature(MainRS)] +VSOutput VSBasicVc(VSInputVc vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: vertex color, no fog. +[RootSignature(MainRS)] +VSOutputNoFog VSBasicVcNoFog(VSInputVc vin) +{ + VSOutputNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: texture. +[RootSignature(MainRS)] +VSOutputTx VSBasicTx(VSInputTx vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: texture, no fog. +[RootSignature(MainRS)] +VSOutputTxNoFog VSBasicTxNoFog(VSInputTx vin) +{ + VSOutputTxNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: texture + vertex color. +[RootSignature(MainRS)] +VSOutputTx VSBasicTxVc(VSInputTxVc vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: texture + vertex color, no fog. +[RootSignature(MainRS)] +VSOutputTxNoFog VSBasicTxVcNoFog(VSInputTxVc vin) +{ + VSOutputTxNoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: vertex lighting. +[RootSignature(MainRS)] +VSOutput VSBasicVertexLighting(VSInputNm vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + return vout; +} + + +// Vertex shader: vertex lighting + vertex color. +[RootSignature(MainRS)] +VSOutput VSBasicVertexLightingVc(VSInputNmVc vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: vertex lighting + texture. +[RootSignature(MainRS)] +VSOutputTx VSBasicVertexLightingTx(VSInputNmTx vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: vertex lighting + texture + vertex color. +[RootSignature(MainRS)] +VSOutputTx VSBasicVertexLightingTxVc(VSInputNmTxVc vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: one light. +[RootSignature(MainRS)] +VSOutput VSBasicOneLight(VSInputNm vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + return vout; +} + + +// Vertex shader: one light + vertex color. +[RootSignature(MainRS)] +VSOutput VSBasicOneLightVc(VSInputNmVc vin) +{ + VSOutput vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: one light + texture. +[RootSignature(MainRS)] +VSOutputTx VSBasicOneLightTx(VSInputNmTx vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: one light + texture + vertex color. +[RootSignature(MainRS)] +VSOutputTx VSBasicOneLightTxVc(VSInputNmTxVc vin) +{ + VSOutputTx vout; + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: pixel lighting. +[RootSignature(MainRS)] +VSOutputPixelLighting VSBasicPixelLighting(VSInputNm vin) +{ + VSOutputPixelLighting vout; + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + + return vout; +} + + +// Vertex shader: pixel lighting + vertex color. +[RootSignature(MainRS)] +VSOutputPixelLighting VSBasicPixelLightingVc(VSInputNmVc vin) +{ + VSOutputPixelLighting vout; + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * DiffuseColor.a; + + return vout; +} + + +// Vertex shader: pixel lighting + texture. +[RootSignature(MainRS)] +VSOutputPixelLightingTx VSBasicPixelLightingTx(VSInputNmTx vin) +{ + VSOutputPixelLightingTx vout; + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: pixel lighting + texture + vertex color. +[RootSignature(MainRS)] +VSOutputPixelLightingTx VSBasicPixelLightingTxVc(VSInputNmTxVc vin) +{ + VSOutputPixelLightingTx vout; + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * DiffuseColor.a; + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Pixel shader: basic. +[RootSignature(MainRS)] +float4 PSBasic(PSInput pin) : SV_Target0 +{ + float4 color = pin.Diffuse; + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: no fog. +[RootSignature(MainRS)] +float4 PSBasicNoFog(PSInputNoFog pin) : SV_Target0 +{ + return pin.Diffuse; +} + + +// Pixel shader: texture. +[RootSignature(MainRS)] +float4 PSBasicTx(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: texture, no fog. +[RootSignature(MainRS)] +float4 PSBasicTxNoFog(PSInputTxNoFog pin) : SV_Target0 +{ + return Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; +} + + +// Pixel shader: vertex lighting. +[RootSignature(MainRS)] +float4 PSBasicVertexLighting(PSInput pin) : SV_Target0 +{ + float4 color = pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: vertex lighting, no fog. +[RootSignature(MainRS)] +float4 PSBasicVertexLightingNoFog(PSInput pin) : SV_Target0 +{ + float4 color = pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + + return color; +} + + +// Pixel shader: vertex lighting + texture. +[RootSignature(MainRS)] +float4 PSBasicVertexLightingTx(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: vertex lighting + texture, no fog. +[RootSignature(MainRS)] +float4 PSBasicVertexLightingTxNoFog(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + + return color; +} + + +// Pixel shader: pixel lighting. +[RootSignature(MainRS)] +float4 PSBasicPixelLighting(PSInputPixelLighting pin) : SV_Target0 +{ + float4 color = pin.Diffuse; + + float3 eyeVector = normalize(EyePosition - pin.PositionWS.xyz); + float3 worldNormal = normalize(pin.NormalWS); + + ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 3); + + color.rgb *= lightResult.Diffuse; + + AddSpecular(color, lightResult.Specular); + ApplyFog(color, pin.PositionWS.w); + + return color; +} + + +// Pixel shader: pixel lighting + texture. +[RootSignature(MainRS)] +float4 PSBasicPixelLightingTx(PSInputPixelLightingTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + float3 eyeVector = normalize(EyePosition - pin.PositionWS.xyz); + float3 worldNormal = normalize(pin.NormalWS); + + ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 3); + + color.rgb *= lightResult.Diffuse; + + AddSpecular(color, lightResult.Specular); + ApplyFog(color, pin.PositionWS.w); + + return color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/Common.fxh b/Kits/DirectXTK12/Src/Shaders/Common.fxh new file mode 100644 index 00000000..54ffe4e0 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Common.fxh @@ -0,0 +1,60 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +float ComputeFogFactor(float4 position) +{ + return saturate(dot(position, FogVector)); +} + + +void ApplyFog(inout float4 color, float fogFactor) +{ + color.rgb = lerp(color.rgb, FogColor * color.a, fogFactor); +} + + +void AddSpecular(inout float4 color, float3 specular) +{ + color.rgb += specular * color.a; +} + + +struct CommonVSOutput +{ + float4 Pos_ps; + float4 Diffuse; + float3 Specular; + float FogFactor; +}; + + +CommonVSOutput ComputeCommonVSOutput(float4 position) +{ + CommonVSOutput vout; + + vout.Pos_ps = mul(position, WorldViewProj); + vout.Diffuse = DiffuseColor; + vout.Specular = 0; + vout.FogFactor = ComputeFogFactor(position); + + return vout; +} + + +#define SetCommonVSOutputParams \ + vout.PositionPS = cout.Pos_ps; \ + vout.Diffuse = cout.Diffuse; \ + vout.Specular = float4(cout.Specular, cout.FogFactor); + + +#define SetCommonVSOutputParamsNoFog \ + vout.PositionPS = cout.Pos_ps; \ + vout.Diffuse = cout.Diffuse; diff --git a/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd b/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd new file mode 100644 index 00000000..30e9bcbe --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/CompileShaders.cmd @@ -0,0 +1,166 @@ +@echo off +rem THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +rem ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +rem THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +rem PARTICULAR PURPOSE. +rem +rem Copyright (c) Microsoft Corporation. All rights reserved. + +setlocal +set error=0 + +if %1.==xbox. goto continuexbox +if %1.==. goto continue +echo usage: CompileShaders [xbox] +exit /b + +:continuexbox +set XBOXFXC="%XboxOneXDKLatest%xdk\FXC\amd64\FXC.exe" +if exist %XBOXFXC% goto continue +set XBOXFXC="%XboxOneXDKBuild%xdk\FXC\amd64\FXC.exe" +if exist %XBOXFXC% goto continue +set XBOXFXC="%DurangoXDK%xdk\FXC\amd64\FXC.exe" +if not exist %XBOXFXC% goto needxdk + +:continue + +call :CompileShader%1 AlphaTestEffect vs VSAlphaTest +call :CompileShader%1 AlphaTestEffect vs VSAlphaTestNoFog +call :CompileShader%1 AlphaTestEffect vs VSAlphaTestVc +call :CompileShader%1 AlphaTestEffect vs VSAlphaTestVcNoFog + +call :CompileShader%1 AlphaTestEffect ps PSAlphaTestLtGt +call :CompileShader%1 AlphaTestEffect ps PSAlphaTestLtGtNoFog +call :CompileShader%1 AlphaTestEffect ps PSAlphaTestEqNe +call :CompileShader%1 AlphaTestEffect ps PSAlphaTestEqNeNoFog + +call :CompileShader%1 BasicEffect vs VSBasic +call :CompileShader%1 BasicEffect vs VSBasicNoFog +call :CompileShader%1 BasicEffect vs VSBasicVc +call :CompileShader%1 BasicEffect vs VSBasicVcNoFog +call :CompileShader%1 BasicEffect vs VSBasicTx +call :CompileShader%1 BasicEffect vs VSBasicTxNoFog +call :CompileShader%1 BasicEffect vs VSBasicTxVc +call :CompileShader%1 BasicEffect vs VSBasicTxVcNoFog + +call :CompileShader%1 BasicEffect vs VSBasicVertexLighting +call :CompileShader%1 BasicEffect vs VSBasicVertexLightingVc +call :CompileShader%1 BasicEffect vs VSBasicVertexLightingTx +call :CompileShader%1 BasicEffect vs VSBasicVertexLightingTxVc + +call :CompileShader%1 BasicEffect vs VSBasicOneLight +call :CompileShader%1 BasicEffect vs VSBasicOneLightVc +call :CompileShader%1 BasicEffect vs VSBasicOneLightTx +call :CompileShader%1 BasicEffect vs VSBasicOneLightTxVc + +call :CompileShader%1 BasicEffect vs VSBasicPixelLighting +call :CompileShader%1 BasicEffect vs VSBasicPixelLightingVc +call :CompileShader%1 BasicEffect vs VSBasicPixelLightingTx +call :CompileShader%1 BasicEffect vs VSBasicPixelLightingTxVc + +call :CompileShader%1 BasicEffect ps PSBasic +call :CompileShader%1 BasicEffect ps PSBasicNoFog +call :CompileShader%1 BasicEffect ps PSBasicTx +call :CompileShader%1 BasicEffect ps PSBasicTxNoFog + +call :CompileShader%1 BasicEffect ps PSBasicVertexLighting +call :CompileShader%1 BasicEffect ps PSBasicVertexLightingNoFog +call :CompileShader%1 BasicEffect ps PSBasicVertexLightingTx +call :CompileShader%1 BasicEffect ps PSBasicVertexLightingTxNoFog + +call :CompileShader%1 BasicEffect ps PSBasicPixelLighting +call :CompileShader%1 BasicEffect ps PSBasicPixelLightingTx + +call :CompileShader%1 DualTextureEffect vs VSDualTexture +call :CompileShader%1 DualTextureEffect vs VSDualTextureNoFog +call :CompileShader%1 DualTextureEffect vs VSDualTextureVc +call :CompileShader%1 DualTextureEffect vs VSDualTextureVcNoFog + +call :CompileShader%1 DualTextureEffect ps PSDualTexture +call :CompileShader%1 DualTextureEffect ps PSDualTextureNoFog + +call :CompileShader%1 EnvironmentMapEffect vs VSEnvMap +call :CompileShader%1 EnvironmentMapEffect vs VSEnvMapFresnel +call :CompileShader%1 EnvironmentMapEffect vs VSEnvMapOneLight +call :CompileShader%1 EnvironmentMapEffect vs VSEnvMapOneLightFresnel + +call :CompileShader%1 EnvironmentMapEffect ps PSEnvMap +call :CompileShader%1 EnvironmentMapEffect ps PSEnvMapNoFog +call :CompileShader%1 EnvironmentMapEffect ps PSEnvMapSpecular +call :CompileShader%1 EnvironmentMapEffect ps PSEnvMapSpecularNoFog + +call :CompileShader%1 SkinnedEffect vs VSSkinnedVertexLightingOneBone +call :CompileShader%1 SkinnedEffect vs VSSkinnedVertexLightingTwoBones +call :CompileShader%1 SkinnedEffect vs VSSkinnedVertexLightingFourBones + +call :CompileShader%1 SkinnedEffect vs VSSkinnedOneLightOneBone +call :CompileShader%1 SkinnedEffect vs VSSkinnedOneLightTwoBones +call :CompileShader%1 SkinnedEffect vs VSSkinnedOneLightFourBones + +call :CompileShader%1 SkinnedEffect vs VSSkinnedPixelLightingOneBone +call :CompileShader%1 SkinnedEffect vs VSSkinnedPixelLightingTwoBones +call :CompileShader%1 SkinnedEffect vs VSSkinnedPixelLightingFourBones + +call :CompileShader%1 SkinnedEffect ps PSSkinnedVertexLighting +call :CompileShader%1 SkinnedEffect ps PSSkinnedVertexLightingNoFog +call :CompileShader%1 SkinnedEffect ps PSSkinnedPixelLighting + +call :CompileShader%1 SpriteEffect vs SpriteVertexShader +call :CompileShader%1 SpriteEffect ps SpritePixelShader + +call :CompileComputeShader%1 GenerateMips main +echo. + +if %error% == 0 ( + echo Shaders compiled ok +) else ( + echo There were shader compilation errors! +) + +endlocal +exit /b + +:CompileShader +set fxc=fxc /nologo %1.fx /T%2_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /E%3 /FhCompiled\%1_%3.inc /FdCompiled\%1_%3.pdb /Vn%1_%3 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b + +:CompileShaderHLSL +set fxc=fxc /nologo %1.hlsl /T%2_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /E%3 /FhCompiled\%1_%3.inc /FdCompiled\%1_%3.pdb /Vn%1_%3 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b + +:CompileComputeShader +set fxc=fxc /nologo %1.hlsl /Tcs_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /E%2 /FhCompiled\%1_%2.inc /FdCompiled\%1_%2.pdb /Vn%1_%2 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b +:CompileShaderxbox +set fxc=%XBOXFXC% /nologo %1.fx /T%2_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /D__XBOX_DISABLE_SHADER_NAME_EMPLACEMENT /E%3 /FhCompiled\XboxOne%1_%3.inc /FdCompiled\XboxOne%1_%3.pdb /Vn%1_%3 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b + +:CompileShaderHLSLxbox +set fxc=%XBOXFXC% /nologo %1.hlsl /T%2_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /D__XBOX_DISABLE_SHADER_NAME_EMPLACEMENT /E%3 /FhCompiled\XboxOne%1_%3.inc /FdCompiled\XboxOne%1_%3.pdb /Vn%1_%3 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b + +:CompileComputeShaderxbox +set fxc==%XBOXFXC% /nologo %1.hlsl /Tcs_5_0 /Zi /Zpc /Qstrip_reflect /Qstrip_debug /D__XBOX_DISABLE_SHADER_NAME_EMPLACEMENT /E%2 /FhCompiled\XboxOne%1_%2.inc /FdCompiled\XboxOne%1_%2.pdb /Vn%1_%2 +echo. +echo %fxc% +%fxc% || set error=1 +exit /b + +:needxdk +echo ERROR: CompileShaders xbox requires the Microsoft Xbox One XDK +echo (try re-running from the XDK Command Prompt) \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc new file mode 100644 index 00000000..8be6ad15 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNe.inc @@ -0,0 +1,182 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float w +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[3], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.w +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mad r1.x, r0.w, v0.w, -cb0[1].x +mul r0.xyzw, r0.xyzw, v0.xyzw +lt r1.x, |r1.x|, cb0[1].y +movc r1.x, r1.x, cb0[1].z, cb0[1].w +lt r1.x, r1.x, l(0.000000) +discard_nz r1.x +mad r1.xyz, cb0[2].xyzx, r0.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_PSAlphaTestEqNe[] = +{ + 68, 88, 66, 67, 246, 229, + 60, 14, 207, 0, 194, 16, + 172, 158, 131, 17, 251, 44, + 249, 202, 1, 0, 0, 0, + 40, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 152, 2, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 8, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 196, 1, + 0, 0, 80, 0, 0, 0, + 113, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 130, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 16, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 49, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 128, + 129, 0, 0, 0, 1, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 11, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 42, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 49, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 13, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 32, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc new file mode 100644 index 00000000..6bc98d8d --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestEqNeNoFog.inc @@ -0,0 +1,159 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.xyxx, t0.xyzw, s0 +mad r1.x, r0.w, v0.w, -cb0[1].x +mul r0.xyzw, r0.xyzw, v0.xyzw +mov o0.xyzw, r0.xyzw +lt r0.x, |r1.x|, cb0[1].y +movc r0.x, r0.x, cb0[1].z, cb0[1].w +lt r0.x, r0.x, l(0.000000) +discard_nz r0.x +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_PSAlphaTestEqNeNoFog[] = +{ + 68, 88, 66, 67, 167, 227, + 27, 122, 158, 221, 85, 112, + 68, 68, 198, 102, 215, 143, + 72, 162, 1, 0, 0, 0, + 180, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 128, 0, 0, 0, 180, 0, + 0, 0, 36, 2, 0, 0, + 73, 83, 71, 78, 72, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 104, 1, + 0, 0, 80, 0, 0, 0, + 90, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 16, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 49, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 128, 129, 0, 0, 0, + 1, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 55, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 49, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 13, 0, + 4, 3, 10, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc new file mode 100644 index 00000000..24f78ad2 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGt.inc @@ -0,0 +1,173 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float w +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[3], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.w +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +lt r1.x, r0.w, cb0[1].x +movc r1.x, r1.x, cb0[1].z, cb0[1].w +lt r1.x, r1.x, l(0.000000) +discard_nz r1.x +mad r1.xyz, cb0[2].xyzx, r0.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_PSAlphaTestLtGt[] = +{ + 68, 88, 66, 67, 139, 244, + 70, 17, 72, 71, 124, 4, + 47, 166, 100, 136, 165, 85, + 177, 13, 1, 0, 0, 0, + 248, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 104, 2, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 8, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 148, 1, + 0, 0, 80, 0, 0, 0, + 101, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 130, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 49, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 55, 0, 0, 11, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 42, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 49, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 13, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 32, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc new file mode 100644 index 00000000..d6dc7df7 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_PSAlphaTestLtGtNoFog.inc @@ -0,0 +1,150 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +lt r1.x, r0.w, cb0[1].x +mov o0.xyzw, r0.xyzw +movc r0.x, r1.x, cb0[1].z, cb0[1].w +lt r0.x, r0.x, l(0.000000) +discard_nz r0.x +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_PSAlphaTestLtGtNoFog[] = +{ + 68, 88, 66, 67, 234, 228, + 163, 50, 105, 221, 210, 115, + 167, 213, 22, 11, 154, 83, + 176, 199, 1, 0, 0, 0, + 132, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 128, 0, 0, 0, 180, 0, + 0, 0, 244, 1, 0, 0, + 73, 83, 71, 78, 72, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 56, 1, + 0, 0, 80, 0, 0, 0, + 78, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 49, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 55, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 42, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 49, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 13, 0, + 4, 3, 10, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc new file mode 100644 index 00000000..215fa1ac --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTest.inc @@ -0,0 +1,175 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[8], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +mov o0.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[3].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +dp4 o3.x, v0.xyzw, cb0[4].xyzw +dp4 o3.y, v0.xyzw, cb0[5].xyzw +dp4 o3.z, v0.xyzw, cb0[6].xyzw +dp4 o3.w, v0.xyzw, cb0[7].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_VSAlphaTest[] = +{ + 68, 88, 66, 67, 221, 190, + 1, 135, 99, 166, 223, 88, + 57, 207, 182, 209, 221, 22, + 231, 6, 1, 0, 0, 0, + 4, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 136, 0, 0, 0, 20, 1, + 0, 0, 116, 2, 0, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 132, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 104, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 3, 12, + 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 88, 1, + 0, 0, 80, 0, 1, 0, + 86, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc new file mode 100644 index 00000000..d0162d0d --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestNoFog.inc @@ -0,0 +1,154 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[8], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output_siv o2.xyzw, position +mov o0.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +dp4 o2.x, v0.xyzw, cb0[4].xyzw +dp4 o2.y, v0.xyzw, cb0[5].xyzw +dp4 o2.z, v0.xyzw, cb0[6].xyzw +dp4 o2.w, v0.xyzw, cb0[7].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_VSAlphaTestNoFog[] = +{ + 68, 88, 66, 67, 101, 199, + 167, 153, 238, 12, 61, 99, + 72, 61, 191, 121, 181, 83, + 219, 21, 1, 0, 0, 0, + 160, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 136, 0, 0, 0, 252, 0, + 0, 0, 16, 2, 0, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 108, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 86, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 12, + 0, 0, 95, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 12, 1, + 0, 0, 80, 0, 1, 0, + 67, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc new file mode 100644 index 00000000..5284d7f0 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVc.inc @@ -0,0 +1,185 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[8], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +mul o0.xyzw, v2.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[3].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +dp4 o3.x, v0.xyzw, cb0[4].xyzw +dp4 o3.y, v0.xyzw, cb0[5].xyzw +dp4 o3.z, v0.xyzw, cb0[6].xyzw +dp4 o3.w, v0.xyzw, cb0[7].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_VSAlphaTestVc[] = +{ + 68, 88, 66, 67, 68, 140, + 236, 178, 51, 120, 159, 181, + 137, 177, 117, 230, 67, 55, + 161, 161, 1, 0, 0, 0, + 52, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 48, 1, + 0, 0, 164, 2, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 104, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 108, 1, 0, 0, + 80, 0, 1, 0, 91, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc new file mode 100644 index 00000000..3c399277 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/AlphaTestEffect_VSAlphaTestVcNoFog.inc @@ -0,0 +1,164 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[8], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output_siv o2.xyzw, position +mul o0.xyzw, v2.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +dp4 o2.x, v0.xyzw, cb0[4].xyzw +dp4 o2.y, v0.xyzw, cb0[5].xyzw +dp4 o2.z, v0.xyzw, cb0[6].xyzw +dp4 o2.w, v0.xyzw, cb0[7].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE AlphaTestEffect_VSAlphaTestVcNoFog[] = +{ + 68, 88, 66, 67, 250, 244, + 57, 14, 109, 121, 124, 244, + 77, 227, 64, 98, 34, 172, + 148, 18, 1, 0, 0, 0, + 208, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 24, 1, + 0, 0, 64, 2, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 108, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 86, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 95, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 32, 1, 0, 0, + 80, 0, 1, 0, 72, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasic.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasic.inc new file mode 100644 index 00000000..fff3b087 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasic.inc @@ -0,0 +1,120 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float w +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.w +dcl_output o0.xyzw +dcl_temps 1 +mad r0.xyz, cb0[13].xyzx, v0.wwww, -v0.xyzx +mad o0.xyz, v1.wwww, r0.xyzx, v0.xyzx +mov o0.w, v0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasic[] = +{ + 68, 88, 66, 67, 183, 60, + 196, 208, 177, 115, 92, 82, + 111, 165, 146, 165, 113, 31, + 214, 112, 1, 0, 0, 0, + 244, 1, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 120, 0, 0, 0, 172, 0, + 0, 0, 100, 1, 0, 0, + 73, 83, 71, 78, 64, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 56, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 8, 0, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 176, 0, 0, 0, + 80, 0, 0, 0, 44, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 130, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 31, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 31, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 16, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc new file mode 100644 index 00000000..de39ffd6 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicNoFog.inc @@ -0,0 +1,90 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_input_ps linear v0.xyzw +dcl_output o0.xyzw +mov o0.xyzw, v0.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicNoFog[] = +{ + 68, 88, 66, 67, 58, 161, + 116, 209, 214, 104, 20, 135, + 146, 234, 83, 150, 47, 95, + 231, 68, 1, 0, 0, 0, + 104, 1, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 96, 0, 0, 0, 148, 0, + 0, 0, 216, 0, 0, 0, + 73, 83, 71, 78, 40, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 60, 0, 0, 0, + 80, 0, 0, 0, 15, 0, + 0, 0, 106, 8, 0, 1, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc new file mode 100644 index 00000000..7247dcc8 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLighting.inc @@ -0,0 +1,392 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xyzw 0 NONE float xyzw +// TEXCOORD 1 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 4 +add r0.xyz, -v0.xyzx, cb0[12].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mad r1.xyz, r0.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r1.xyzx, r1.xyzx +rsq r1.w, r1.w +mul r1.xyz, r1.wwww, r1.xyzx +dp3 r1.w, v1.xyzx, v1.xyzx +rsq r1.w, r1.w +mul r2.xyz, r1.wwww, v1.xyzx +dp3 r1.x, r1.xyzx, r2.xyzx +mad r3.xyz, r0.xyzx, r0.wwww, -cb0[4].xyzx +mad r0.xyz, r0.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul r3.xyz, r0.wwww, r3.xyzx +dp3 r1.y, r3.xyzx, r2.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.z, r0.xyzx, r2.xyzx +max r0.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +dp3 r1.x, -cb0[3].xyzx, r2.xyzx +dp3 r1.y, -cb0[4].xyzx, r2.xyzx +dp3 r1.z, -cb0[5].xyzx, r2.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r0.xyz, r0.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r2.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul r0.xyz, r0.xyzx, cb0[2].xyzx +mul r0.xyz, r0.xyzx, v2.wwww +mul r2.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r2.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad r1.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mad r0.xyz, v2.xyzx, r1.xyzx, r0.xyzx +mad r1.xyz, cb0[13].xyzx, v2.wwww, -r0.xyzx +mad o0.xyz, v0.wwww, r1.xyzx, r0.xyzx +mov o0.w, v2.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicPixelLighting[] = +{ + 68, 88, 66, 67, 80, 119, + 109, 150, 219, 119, 195, 227, + 25, 193, 36, 62, 131, 64, + 117, 159, 1, 0, 0, 0, + 76, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 188, 6, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 89, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 232, 5, + 0, 0, 80, 0, 0, 0, + 122, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 0, 0, 0, 9, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 9, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 29, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 47, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 143, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 70, 8, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 0, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 70, 3, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 70, 3, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 31, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 31, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 16, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc new file mode 100644 index 00000000..4f0b8ce7 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicPixelLightingTx.inc @@ -0,0 +1,420 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xyz +dcl_input_ps linear v3.xyzw +dcl_output o0.xyzw +dcl_temps 4 +add r0.xyz, -v1.xyzx, cb0[12].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mad r1.xyz, r0.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r1.xyzx, r1.xyzx +rsq r1.w, r1.w +mul r1.xyz, r1.wwww, r1.xyzx +dp3 r1.w, v2.xyzx, v2.xyzx +rsq r1.w, r1.w +mul r2.xyz, r1.wwww, v2.xyzx +dp3 r1.x, r1.xyzx, r2.xyzx +mad r3.xyz, r0.xyzx, r0.wwww, -cb0[4].xyzx +mad r0.xyz, r0.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul r3.xyz, r0.wwww, r3.xyzx +dp3 r1.y, r3.xyzx, r2.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.z, r0.xyzx, r2.xyzx +max r0.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +dp3 r1.x, -cb0[3].xyzx, r2.xyzx +dp3 r1.y, -cb0[4].xyzx, r2.xyzx +dp3 r1.z, -cb0[5].xyzx, r2.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r0.xyz, r0.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r2.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul r0.xyz, r0.xyzx, cb0[2].xyzx +sample_indexable(texture2d)(float,float,float,float) r2.xyzw, v0.xyxx, t0.xyzw, s0 +mul r2.xyzw, r2.xyzw, v3.xyzw +mul r0.xyz, r0.xyzx, r2.wwww +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad r1.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mad r0.xyz, r2.xyzx, r1.xyzx, r0.xyzx +mad r1.xyz, cb0[13].xyzx, r2.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r2.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicPixelLightingTx[] = +{ + 68, 88, 66, 67, 205, 238, + 143, 140, 178, 65, 203, 209, + 67, 78, 138, 68, 75, 82, + 38, 112, 1, 0, 0, 0, + 212, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 68, 7, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 113, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 88, 6, + 0, 0, 80, 0, 0, 0, + 150, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 114, 16, 16, 0, + 2, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 4, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 18, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 2, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 50, 0, 0, 10, 178, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 136, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 10, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 70, 3, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 32, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc new file mode 100644 index 00000000..dc8a862e --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTx.inc @@ -0,0 +1,150 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float w +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.w +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +mad r1.xyz, cb0[13].xyzx, r0.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicTx[] = +{ + 68, 88, 66, 67, 162, 232, + 220, 1, 165, 64, 33, 107, + 255, 154, 86, 105, 51, 250, + 4, 165, 1, 0, 0, 0, + 132, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 244, 1, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 8, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 32, 1, + 0, 0, 80, 0, 0, 0, + 72, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 130, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 31, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc new file mode 100644 index 00000000..a21cb801 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicTxNoFog.inc @@ -0,0 +1,118 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 1 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.xyxx, t0.xyzw, s0 +mul o0.xyzw, r0.xyzw, v0.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicTxNoFog[] = +{ + 68, 88, 66, 67, 139, 129, + 110, 56, 73, 191, 71, 92, + 53, 195, 34, 82, 243, 212, + 243, 147, 1, 0, 0, 0, + 236, 1, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 128, 0, 0, 0, 180, 0, + 0, 0, 92, 1, 0, 0, + 73, 83, 71, 78, 72, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 160, 0, + 0, 0, 80, 0, 0, 0, + 40, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc new file mode 100644 index 00000000..e19928f5 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLighting.inc @@ -0,0 +1,127 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyzw +dcl_output o0.xyzw +dcl_temps 2 +mad r0.xyz, v1.xyzx, v0.wwww, v0.xyzx +mad r1.xyz, cb0[13].xyzx, v0.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, v0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicVertexLighting[] = +{ + 68, 88, 66, 67, 31, 92, + 30, 4, 201, 166, 30, 4, + 49, 191, 200, 228, 6, 176, + 146, 104, 1, 0, 0, 0, + 24, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 120, 0, 0, 0, 172, 0, + 0, 0, 136, 1, 0, 0, + 73, 83, 71, 78, 64, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 56, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 212, 0, 0, 0, + 80, 0, 0, 0, 53, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 246, 31, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 31, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 31, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 16, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc new file mode 100644 index 00000000..ee3122e0 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingNoFog.inc @@ -0,0 +1,105 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_output o0.xyzw +mad o0.xyz, v1.xyzx, v0.wwww, v0.xyzx +mov o0.w, v0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicVertexLightingNoFog[] = +{ + 68, 88, 66, 67, 71, 10, + 125, 168, 154, 176, 219, 94, + 67, 33, 136, 223, 81, 243, + 31, 11, 1, 0, 0, 0, + 176, 1, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 120, 0, 0, 0, 172, 0, + 0, 0, 32, 1, 0, 0, + 73, 83, 71, 78, 64, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 56, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 7, 0, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 108, 0, 0, 0, + 80, 0, 0, 0, 27, 0, + 0, 0, 106, 8, 0, 1, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 246, 31, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc new file mode 100644 index 00000000..44c3d39b --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTx.inc @@ -0,0 +1,157 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +mad r0.xyz, v1.xyzx, r0.wwww, r0.xyzx +mad r1.xyz, cb0[13].xyzx, r0.wwww, -r0.xyzx +mov o0.w, r0.w +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicVertexLightingTx[] = +{ + 68, 88, 66, 67, 34, 223, + 3, 44, 153, 63, 227, 172, + 41, 191, 222, 82, 131, 245, + 43, 22, 1, 0, 0, 0, + 168, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 24, 2, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 68, 1, + 0, 0, 80, 0, 0, 0, + 81, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 32, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc new file mode 100644 index 00000000..3d61faad --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_PSBasicVertexLightingTxNoFog.inc @@ -0,0 +1,138 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 1 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +mad o0.xyz, v1.xyzx, r0.wwww, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_PSBasicVertexLightingTxNoFog[] = +{ + 68, 88, 66, 67, 164, 58, + 62, 66, 161, 173, 104, 194, + 104, 188, 84, 59, 140, 69, + 107, 145, 1, 0, 0, 0, + 72, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 184, 1, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 7, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 228, 0, + 0, 0, 80, 0, 0, 0, + 57, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasic.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasic.inc new file mode 100644 index 00000000..eee7ff73 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasic.inc @@ -0,0 +1,151 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +mov o0.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o1.xyz, l(0,0,0,0) +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasic[] = +{ + 68, 88, 66, 67, 171, 205, + 230, 20, 233, 2, 32, 110, + 209, 17, 101, 27, 25, 114, + 120, 158, 1, 0, 0, 0, + 148, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 100, 0, 0, 0, 208, 0, + 0, 0, 4, 2, 0, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 100, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 80, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 86, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 171, 171, 83, 72, + 69, 88, 44, 1, 0, 0, + 80, 0, 1, 0, 75, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 54, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 25, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc new file mode 100644 index 00000000..6038eb7e --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicNoFog.inc @@ -0,0 +1,131 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// SV_Position 0 xyzw 1 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_output o0.xyzw +dcl_output_siv o1.xyzw, position +mov o0.xyzw, cb0[0].xyzw +dp4 o1.x, v0.xyzw, cb0[22].xyzw +dp4 o1.y, v0.xyzw, cb0[23].xyzw +dp4 o1.z, v0.xyzw, cb0[24].xyzw +dp4 o1.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicNoFog[] = +{ + 68, 88, 66, 67, 144, 119, + 211, 194, 50, 207, 226, 145, + 113, 190, 13, 247, 166, 229, + 194, 196, 1, 0, 0, 0, + 48, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 100, 0, 0, 0, 184, 0, + 0, 0, 160, 1, 0, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 76, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 62, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 171, 171, 83, 72, + 69, 88, 224, 0, 0, 0, + 80, 0, 1, 0, 56, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc new file mode 100644 index 00000000..7320572a --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLight.inc @@ -0,0 +1,335 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.yzw, r0.wwww, cb0[6].xxyz +mad o0.xyz, r1.yzwy, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +dp4 r2.x, v0.xyzw, cb0[15].xyzw +dp4 r2.y, v0.xyzw, cb0[16].xyzw +dp4 r2.z, v0.xyzw, cb0[17].xyzw +add r1.yzw, -r2.xxyz, cb0[12].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mad r1.yzw, r1.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mul r1.yzw, r0.wwww, r1.yyzw +dp3 r0.x, r1.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r1.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicOneLight[] = +{ + 68, 88, 66, 67, 205, 187, + 83, 238, 154, 120, 243, 11, + 92, 1, 22, 178, 29, 9, + 165, 0, 1, 0, 0, 0, + 32, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 132, 0, 0, 0, 240, 0, + 0, 0, 144, 5, 0, 0, + 73, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 171, + 79, 83, 71, 78, 100, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 171, 171, + 83, 72, 69, 88, 152, 4, + 0, 0, 80, 0, 1, 0, + 38, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 3, 0, 0, 0, + 16, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 19, 0, + 0, 0, 16, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 16, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 29, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 56, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 8, 226, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 226, 0, 16, 0, 1, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 1, 0, + 0, 0, 86, 14, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 226, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc new file mode 100644 index 00000000..6d84cdf3 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTx.inc @@ -0,0 +1,358 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.yzw, r0.wwww, cb0[6].xxyz +mad o0.xyz, r1.yzwy, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +dp4 r2.x, v0.xyzw, cb0[15].xyzw +dp4 r2.y, v0.xyzw, cb0[16].xyzw +dp4 r2.z, v0.xyzw, cb0[17].xyzw +add r1.yzw, -r2.xxyz, cb0[12].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mad r1.yzw, r1.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mul r1.yzw, r0.wwww, r1.yyzw +dp3 r0.x, r1.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r1.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicOneLightTx[] = +{ + 68, 88, 66, 67, 252, 138, + 84, 165, 124, 145, 38, 173, + 137, 62, 237, 53, 36, 157, + 123, 84, 1, 0, 0, 0, + 140, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 48, 1, + 0, 0, 252, 5, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 104, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 196, 4, 0, 0, + 80, 0, 1, 0, 49, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 3, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 226, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 17, 0, 0, 8, 18, 0, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 17, 0, 0, 8, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 17, 0, + 0, 8, 66, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 0, 0, 0, 9, 226, 0, + 16, 0, 1, 0, 0, 0, + 6, 9, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 6, 137, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 226, 0, + 16, 0, 1, 0, 0, 0, + 86, 14, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 137, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 226, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 86, 14, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 56, 0, 0, 8, + 114, 32, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc new file mode 100644 index 00000000..5e37181f --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightTxVc.inc @@ -0,0 +1,374 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.yzw, r0.wwww, cb0[6].xxyz +mad r1.yzw, r1.yyzw, cb0[0].xxyz, cb0[1].xxyz +mul o0.xyz, r1.yzwy, v3.xyzx +mul o0.w, v3.w, cb0[0].w +dp4 r2.x, v0.xyzw, cb0[15].xyzw +dp4 r2.y, v0.xyzw, cb0[16].xyzw +dp4 r2.z, v0.xyzw, cb0[17].xyzw +add r1.yzw, -r2.xxyz, cb0[12].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mad r1.yzw, r1.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mul r1.yzw, r0.wwww, r1.yyzw +dp3 r0.x, r1.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r1.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicOneLightTxVc[] = +{ + 68, 88, 66, 67, 24, 212, + 100, 197, 10, 221, 20, 255, + 101, 83, 94, 253, 47, 95, + 104, 135, 1, 0, 0, 0, + 220, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 196, 0, 0, 0, 80, 1, + 0, 0, 76, 6, 0, 0, + 73, 83, 71, 78, 140, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 123, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 132, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 171, 171, 79, 83, + 71, 78, 132, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 104, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 3, 12, + 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 244, 4, + 0, 0, 80, 0, 1, 0, + 61, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 3, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 3, 0, 0, 0, + 16, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 19, 0, + 0, 0, 16, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 16, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 29, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 56, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 8, 226, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 50, 0, 0, 11, 226, 0, + 16, 0, 1, 0, 0, 0, + 86, 14, 16, 0, 1, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 114, 32, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 70, 18, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 8, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 3, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 226, 0, 16, 0, 1, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 1, 0, + 0, 0, 86, 14, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 226, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc new file mode 100644 index 00000000..a2d7669c --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicOneLightVc.inc @@ -0,0 +1,351 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.yzw, r0.wwww, cb0[6].xxyz +mad r1.yzw, r1.yyzw, cb0[0].xxyz, cb0[1].xxyz +mul o0.xyz, r1.yzwy, v2.xyzx +mul o0.w, v2.w, cb0[0].w +dp4 r2.x, v0.xyzw, cb0[15].xyzw +dp4 r2.y, v0.xyzw, cb0[16].xyzw +dp4 r2.z, v0.xyzw, cb0[17].xyzw +add r1.yzw, -r2.xxyz, cb0[12].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mad r1.yzw, r1.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r1.yzwy, r1.yzwy +rsq r0.w, r0.w +mul r1.yzw, r0.wwww, r1.yyzw +dp3 r0.x, r1.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r1.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicOneLightVc[] = +{ + 68, 88, 66, 67, 45, 15, + 24, 39, 17, 51, 114, 208, + 10, 54, 206, 175, 244, 212, + 243, 90, 1, 0, 0, 0, + 112, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 16, 1, + 0, 0, 224, 5, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 67, + 79, 76, 79, 82, 0, 171, + 171, 171, 79, 83, 71, 78, + 100, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 80, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 86, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 171, 171, 83, 72, 69, 88, + 200, 4, 0, 0, 80, 0, + 1, 0, 50, 1, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 26, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 16, 0, 0, 8, + 18, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 20, 0, 0, 0, + 16, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 21, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 29, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 8, 226, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 1, 0, + 0, 0, 86, 14, 16, 0, + 1, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 70, 18, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 16, 16, 0, + 2, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 226, 0, 16, 0, + 1, 0, 0, 0, 6, 9, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 226, 0, 16, 0, + 1, 0, 0, 0, 86, 14, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 6, 137, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 1, 0, + 0, 0, 150, 7, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 226, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 86, 14, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 52, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 47, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 25, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 56, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc new file mode 100644 index 00000000..4f1cfb49 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLighting.inc @@ -0,0 +1,226 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xyzw 0 NONE float xyzw +// TEXCOORD 1 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_output o0.xyzw +dcl_output o1.xyz +dcl_output o2.xyzw +dcl_output_siv o3.xyzw, position +dcl_temps 1 +dp4 o0.x, v0.xyzw, cb0[15].xyzw +dp4 o0.y, v0.xyzw, cb0[16].xyzw +dp4 o0.z, v0.xyzw, cb0[17].xyzw +dp4_sat o0.w, v0.xyzw, cb0[14].xyzw +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o1.xyz, r0.wwww, r0.xyzx +mov o2.xyz, l(1.000000,1.000000,1.000000,0) +mov o2.w, cb0[0].w +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicPixelLighting[] = +{ + 68, 88, 66, 67, 123, 23, + 144, 57, 219, 78, 135, 217, + 87, 168, 89, 226, 235, 100, + 64, 73, 1, 0, 0, 0, + 0, 4, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 132, 0, 0, 0, 16, 1, + 0, 0, 112, 3, 0, 0, + 73, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 8, 0, 0, 113, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 0, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 88, 2, 0, 0, 80, 0, + 1, 0, 150, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 26, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 114, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 114, 32, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 32, 16, 0, + 2, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc new file mode 100644 index 00000000..b324112e --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTx.inc @@ -0,0 +1,248 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xy +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyzw +dcl_output_siv o4.xyzw, position +dcl_temps 1 +mov o0.xy, v2.xyxx +dp4 o1.x, v0.xyzw, cb0[15].xyzw +dp4 o1.y, v0.xyzw, cb0[16].xyzw +dp4 o1.z, v0.xyzw, cb0[17].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r0.xyzx +mov o3.xyz, l(1.000000,1.000000,1.000000,0) +mov o3.w, cb0[0].w +dp4 o4.x, v0.xyzw, cb0[22].xyzw +dp4 o4.y, v0.xyzw, cb0[23].xyzw +dp4 o4.z, v0.xyzw, cb0[24].xyzw +dp4 o4.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicPixelLightingTx[] = +{ + 68, 88, 66, 67, 255, 247, + 52, 216, 247, 126, 208, 221, + 159, 136, 128, 158, 202, 40, + 148, 150, 1, 0, 0, 0, + 100, 4, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 72, 1, + 0, 0, 212, 3, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 12, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 7, 8, 0, 0, + 137, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 67, 79, 76, + 79, 82, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 132, 2, 0, 0, + 80, 0, 1, 0, 161, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 3, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 16, 0, 0, 8, + 18, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 20, 0, 0, 0, + 16, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 21, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 32, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 3, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc new file mode 100644 index 00000000..37fcf481 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingTxVc.inc @@ -0,0 +1,256 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_output o0.xy +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyzw +dcl_output_siv o4.xyzw, position +dcl_temps 1 +mov o0.xy, v2.xyxx +dp4 o1.x, v0.xyzw, cb0[15].xyzw +dp4 o1.y, v0.xyzw, cb0[16].xyzw +dp4 o1.z, v0.xyzw, cb0[17].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r0.xyzx +mul o3.w, v3.w, cb0[0].w +mov o3.xyz, v3.xyzx +dp4 o4.x, v0.xyzw, cb0[22].xyzw +dp4 o4.y, v0.xyzw, cb0[23].xyzw +dp4 o4.z, v0.xyzw, cb0[24].xyzw +dp4 o4.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicPixelLightingTxVc[] = +{ + 68, 88, 66, 67, 189, 67, + 72, 46, 89, 194, 134, 249, + 140, 53, 177, 146, 7, 35, + 112, 212, 1, 0, 0, 0, + 140, 4, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 196, 0, 0, 0, 104, 1, + 0, 0, 252, 3, 0, 0, + 73, 83, 71, 78, 140, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 123, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 132, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 171, 171, 79, 83, + 71, 78, 156, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 12, + 0, 0, 128, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 128, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 7, 8, + 0, 0, 137, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 143, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 4, 0, 0, 0, 15, 0, + 0, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 67, + 79, 76, 79, 82, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 140, 2, + 0, 0, 80, 0, 1, 0, + 163, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 3, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 114, 32, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 3, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 4, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 130, 32, 16, 0, 3, 0, + 0, 0, 58, 16, 16, 0, + 3, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 114, 32, 16, 0, + 3, 0, 0, 0, 70, 18, + 16, 0, 3, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 25, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc new file mode 100644 index 00000000..fceb71cf --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicPixelLightingVc.inc @@ -0,0 +1,235 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xyzw 0 NONE float xyzw +// TEXCOORD 1 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xyz +dcl_output o2.xyzw +dcl_output_siv o3.xyzw, position +dcl_temps 1 +dp4 o0.x, v0.xyzw, cb0[15].xyzw +dp4 o0.y, v0.xyzw, cb0[16].xyzw +dp4 o0.z, v0.xyzw, cb0[17].xyzw +dp4_sat o0.w, v0.xyzw, cb0[14].xyzw +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o1.xyz, r0.wwww, r0.xyzx +mul o2.w, v2.w, cb0[0].w +mov o2.xyz, v2.xyzx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicPixelLightingVc[] = +{ + 68, 88, 66, 67, 18, 121, + 232, 225, 1, 225, 238, 79, + 246, 90, 6, 77, 56, 232, + 84, 128, 1, 0, 0, 0, + 40, 4, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 48, 1, + 0, 0, 152, 3, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 67, + 79, 76, 79, 82, 0, 171, + 171, 171, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 104, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 7, 8, 0, 0, + 113, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 67, 79, 76, + 79, 82, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 96, 2, 0, 0, + 80, 0, 1, 0, 152, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 16, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 19, 0, + 0, 0, 16, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 16, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 32, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 130, 32, 16, 0, + 2, 0, 0, 0, 58, 16, + 16, 0, 2, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 114, 32, + 16, 0, 2, 0, 0, 0, + 70, 18, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc new file mode 100644 index 00000000..e082869b --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTx.inc @@ -0,0 +1,175 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +mov o0.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicTx[] = +{ + 68, 88, 66, 67, 221, 251, + 208, 100, 43, 35, 132, 199, + 12, 152, 221, 60, 109, 243, + 133, 36, 1, 0, 0, 0, + 4, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 136, 0, 0, 0, 20, 1, + 0, 0, 116, 2, 0, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 132, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 104, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 3, 12, + 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 88, 1, + 0, 0, 80, 0, 1, 0, + 86, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc new file mode 100644 index 00000000..f790aaa5 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxNoFog.inc @@ -0,0 +1,154 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output_siv o2.xyzw, position +mov o0.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicTxNoFog[] = +{ + 68, 88, 66, 67, 138, 43, + 16, 52, 95, 16, 173, 22, + 214, 115, 41, 115, 102, 12, + 105, 159, 1, 0, 0, 0, + 160, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 136, 0, 0, 0, 252, 0, + 0, 0, 16, 2, 0, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 108, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 86, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 12, + 0, 0, 95, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 12, 1, + 0, 0, 80, 0, 1, 0, + 67, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 25, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc new file mode 100644 index 00000000..f5821ede --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVc.inc @@ -0,0 +1,185 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +mul o0.xyzw, v2.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicTxVc[] = +{ + 68, 88, 66, 67, 73, 233, + 255, 88, 37, 104, 152, 178, + 54, 218, 25, 1, 22, 189, + 243, 144, 1, 0, 0, 0, + 52, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 48, 1, + 0, 0, 164, 2, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 104, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 108, 1, 0, 0, + 80, 0, 1, 0, 91, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc new file mode 100644 index 00000000..1bf5e9ac --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicTxVcNoFog.inc @@ -0,0 +1,164 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output_siv o2.xyzw, position +mul o0.xyzw, v2.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicTxVcNoFog[] = +{ + 68, 88, 66, 67, 106, 168, + 188, 243, 85, 145, 202, 24, + 220, 4, 165, 204, 114, 63, + 39, 142, 1, 0, 0, 0, + 208, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 24, 1, + 0, 0, 64, 2, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 108, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 86, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 95, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 32, 1, 0, 0, + 80, 0, 1, 0, 72, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 25, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc new file mode 100644 index 00000000..a61a2320 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVc.inc @@ -0,0 +1,162 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// COLOR 0 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +mul o0.xyzw, v1.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o1.xyz, l(0,0,0,0) +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVc[] = +{ + 68, 88, 66, 67, 202, 59, + 230, 54, 33, 38, 17, 77, + 97, 40, 240, 59, 229, 163, + 167, 115, 1, 0, 0, 0, + 200, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 132, 0, 0, 0, 240, 0, + 0, 0, 56, 2, 0, 0, + 73, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 100, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 171, 171, + 83, 72, 69, 88, 64, 1, + 0, 0, 80, 0, 1, 0, + 80, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 8, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 8, + 114, 32, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc new file mode 100644 index 00000000..434cf9d9 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVcNoFog.inc @@ -0,0 +1,141 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// COLOR 0 xyzw 1 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// SV_Position 0 xyzw 1 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyzw +dcl_output o0.xyzw +dcl_output_siv o1.xyzw, position +mul o0.xyzw, v1.xyzw, cb0[0].xyzw +dp4 o1.x, v0.xyzw, cb0[22].xyzw +dp4 o1.y, v0.xyzw, cb0[23].xyzw +dp4 o1.z, v0.xyzw, cb0[24].xyzw +dp4 o1.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVcNoFog[] = +{ + 68, 88, 66, 67, 176, 224, + 240, 49, 217, 200, 194, 36, + 211, 109, 165, 60, 43, 78, + 154, 144, 1, 0, 0, 0, + 100, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 132, 0, 0, 0, 216, 0, + 0, 0, 212, 1, 0, 0, + 73, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 67, 79, + 76, 79, 82, 0, 171, 171, + 79, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 171, 171, + 83, 72, 69, 88, 244, 0, + 0, 0, 80, 0, 1, 0, + 61, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 8, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 23, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 25, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc new file mode 100644 index 00000000..cbf4db18 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLighting.inc @@ -0,0 +1,445 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +dcl_temps 5 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[3].xyzx, r0.xyzx +dp3 r1.y, -cb0[4].xyzx, r0.xyzx +dp3 r1.z, -cb0[5].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad o0.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +dp4 r1.x, v0.xyzw, cb0[15].xyzw +dp4 r1.y, v0.xyzw, cb0[16].xyzw +dp4 r1.z, v0.xyzw, cb0[17].xyzw +add r1.xyz, -r1.xyzx, cb0[12].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mad r3.xyz, r1.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r3.xyzx, r3.xyzx +rsq r1.w, r1.w +mul r3.xyz, r1.wwww, r3.xyzx +dp3 r3.x, r3.xyzx, r0.xyzx +mad r4.xyz, r1.xyzx, r0.wwww, -cb0[4].xyzx +mad r1.xyz, r1.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r4.xyzx, r4.xyzx +rsq r0.w, r0.w +mul r4.xyz, r0.wwww, r4.xyzx +dp3 r3.y, r4.xyzx, r0.xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r3.z, r1.xyzx, r0.xyzx +max r0.xyz, r3.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r2.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r1.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r1.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVertexLighting[] = +{ + 68, 88, 66, 67, 218, 195, + 148, 176, 26, 158, 220, 114, + 181, 226, 173, 169, 82, 184, + 32, 28, 1, 0, 0, 0, + 84, 8, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 132, 0, 0, 0, 240, 0, + 0, 0, 196, 7, 0, 0, + 73, 83, 71, 78, 76, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 171, + 79, 83, 71, 78, 100, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 171, 171, + 83, 72, 69, 88, 204, 6, + 0, 0, 80, 0, 1, 0, + 179, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 5, 0, 0, 0, + 16, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 19, 0, + 0, 0, 16, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 16, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 29, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 50, 0, 0, 10, 178, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 136, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 10, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 70, 3, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc new file mode 100644 index 00000000..d3c6f2ad --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTx.inc @@ -0,0 +1,468 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 5 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[3].xyzx, r0.xyzx +dp3 r1.y, -cb0[4].xyzx, r0.xyzx +dp3 r1.z, -cb0[5].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad o0.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +dp4 r1.x, v0.xyzw, cb0[15].xyzw +dp4 r1.y, v0.xyzw, cb0[16].xyzw +dp4 r1.z, v0.xyzw, cb0[17].xyzw +add r1.xyz, -r1.xyzx, cb0[12].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mad r3.xyz, r1.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r3.xyzx, r3.xyzx +rsq r1.w, r1.w +mul r3.xyz, r1.wwww, r3.xyzx +dp3 r3.x, r3.xyzx, r0.xyzx +mad r4.xyz, r1.xyzx, r0.wwww, -cb0[4].xyzx +mad r1.xyz, r1.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r4.xyzx, r4.xyzx +rsq r0.w, r0.w +mul r4.xyz, r0.wwww, r4.xyzx +dp3 r3.y, r4.xyzx, r0.xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r3.z, r1.xyzx, r0.xyzx +max r0.xyz, r3.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r2.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r1.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r1.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVertexLightingTx[] = +{ + 68, 88, 66, 67, 192, 69, + 99, 157, 44, 225, 124, 78, + 233, 21, 150, 217, 23, 45, + 116, 186, 1, 0, 0, 0, + 192, 8, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 48, 1, + 0, 0, 48, 8, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 104, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 248, 6, 0, 0, + 80, 0, 1, 0, 190, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 5, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 8, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 1, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 70, 3, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 7, 66, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 52, 0, 0, 10, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 47, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 143, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 25, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 50, 0, 0, 10, 178, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 136, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 70, 8, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 70, 3, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 32, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc new file mode 100644 index 00000000..cdfedb4f --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingTxVc.inc @@ -0,0 +1,484 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 5 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[3].xyzx, r0.xyzx +dp3 r1.y, -cb0[4].xyzx, r0.xyzx +dp3 r1.z, -cb0[5].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad r1.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mul o0.xyz, r1.xyzx, v3.xyzx +mul o0.w, v3.w, cb0[0].w +dp4 r1.x, v0.xyzw, cb0[15].xyzw +dp4 r1.y, v0.xyzw, cb0[16].xyzw +dp4 r1.z, v0.xyzw, cb0[17].xyzw +add r1.xyz, -r1.xyzx, cb0[12].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mad r3.xyz, r1.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r3.xyzx, r3.xyzx +rsq r1.w, r1.w +mul r3.xyz, r1.wwww, r3.xyzx +dp3 r3.x, r3.xyzx, r0.xyzx +mad r4.xyz, r1.xyzx, r0.wwww, -cb0[4].xyzx +mad r1.xyz, r1.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r4.xyzx, r4.xyzx +rsq r0.w, r0.w +mul r4.xyz, r0.wwww, r4.xyzx +dp3 r3.y, r4.xyzx, r0.xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r3.z, r1.xyzx, r0.xyzx +max r0.xyz, r3.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r2.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r1.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r1.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, v0.xyzw, cb0[22].xyzw +dp4 o3.y, v0.xyzw, cb0[23].xyzw +dp4 o3.z, v0.xyzw, cb0[24].xyzw +dp4 o3.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVertexLightingTxVc[] = +{ + 68, 88, 66, 67, 93, 208, + 172, 95, 24, 74, 88, 134, + 98, 249, 84, 250, 108, 129, + 97, 6, 1, 0, 0, 0, + 16, 9, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 196, 0, 0, 0, 80, 1, + 0, 0, 128, 8, 0, 0, + 73, 83, 71, 78, 140, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 123, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 132, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 171, 171, 79, 83, + 71, 78, 132, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 104, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 3, 12, + 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 40, 7, + 0, 0, 80, 0, 1, 0, + 202, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 3, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 5, 0, 0, 0, + 16, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 19, 0, + 0, 0, 16, 0, 0, 8, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 16, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 21, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 29, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 50, 0, 0, 10, 178, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 136, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 10, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 70, 3, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 18, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 8, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 16, 16, 0, + 3, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc new file mode 100644 index 00000000..0016d2b3 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/BasicEffect_VSBasicVertexLightingVc.inc @@ -0,0 +1,461 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[26], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output_siv o2.xyzw, position +dcl_temps 5 +dp3 r0.x, v1.xyzx, cb0[19].xyzx +dp3 r0.y, v1.xyzx, cb0[20].xyzx +dp3 r0.z, v1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[3].xyzx, r0.xyzx +dp3 r1.y, -cb0[4].xyzx, r0.xyzx +dp3 r1.z, -cb0[5].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad r1.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mul o0.xyz, r1.xyzx, v2.xyzx +mul o0.w, v2.w, cb0[0].w +dp4 r1.x, v0.xyzw, cb0[15].xyzw +dp4 r1.y, v0.xyzw, cb0[16].xyzw +dp4 r1.z, v0.xyzw, cb0[17].xyzw +add r1.xyz, -r1.xyzx, cb0[12].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mad r3.xyz, r1.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r3.xyzx, r3.xyzx +rsq r1.w, r1.w +mul r3.xyz, r1.wwww, r3.xyzx +dp3 r3.x, r3.xyzx, r0.xyzx +mad r4.xyz, r1.xyzx, r0.wwww, -cb0[4].xyzx +mad r1.xyz, r1.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r4.xyzx, r4.xyzx +rsq r0.w, r0.w +mul r4.xyz, r0.wwww, r4.xyzx +dp3 r3.y, r4.xyzx, r0.xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r3.z, r1.xyzx, r0.xyzx +max r0.xyz, r3.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r2.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r1.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r1.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, v0.xyzw, cb0[14].xyzw +dp4 o2.x, v0.xyzw, cb0[22].xyzw +dp4 o2.y, v0.xyzw, cb0[23].xyzw +dp4 o2.z, v0.xyzw, cb0[24].xyzw +dp4 o2.w, v0.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE BasicEffect_VSBasicVertexLightingVc[] = +{ + 68, 88, 66, 67, 103, 212, + 119, 83, 173, 89, 117, 173, + 87, 117, 162, 6, 55, 184, + 174, 30, 1, 0, 0, 0, + 164, 8, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 16, 1, + 0, 0, 20, 8, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 67, + 79, 76, 79, 82, 0, 171, + 171, 171, 79, 83, 71, 78, + 100, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 80, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 86, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 171, 171, 83, 72, 69, 88, + 252, 6, 0, 0, 80, 0, + 1, 0, 191, 1, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 26, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 5, 0, + 0, 0, 16, 0, 0, 8, + 18, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 8, 34, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 20, 0, 0, 0, + 16, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 21, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 9, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 9, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 29, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 3, 0, 0, 0, + 86, 5, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 70, 8, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 70, 3, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 16, + 16, 0, 2, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 17, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 17, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 17, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 3, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 143, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 70, 8, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 0, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 70, 3, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc new file mode 100644 index 00000000..251a03dc --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTexture.inc @@ -0,0 +1,201 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float w +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 zw 2 NONE float zw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.w +dcl_input_ps linear v2.xy +dcl_input_ps linear v2.zw +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.zwzz, t1.xyzw, s1 +mul r0.xyzw, r0.xyzw, v0.xyzw +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v2.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, l(2.000000, 2.000000, 2.000000, 1.000000) +mul r0.xyzw, r0.xyzw, r1.xyzw +mad r1.xyz, cb0[1].xyzx, r0.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_PSDualTexture[] = +{ + 68, 88, 66, 67, 84, 118, + 192, 38, 244, 27, 96, 67, + 87, 19, 87, 219, 43, 122, + 231, 144, 1, 0, 0, 0, + 144, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 164, 2, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 8, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 110, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 12, 12, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 184, 1, + 0, 0, 80, 0, 0, 0, + 110, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 1, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 98, 16, 0, 3, + 130, 16, 16, 0, 1, 0, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 98, 16, 0, 3, + 194, 16, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 69, 0, + 0, 139, 194, 0, 0, 128, + 67, 85, 21, 0, 242, 0, + 16, 0, 0, 0, 0, 0, + 230, 26, 16, 0, 2, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 139, 194, 0, 0, 128, + 67, 85, 21, 0, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 70, 126, 16, 0, + 0, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 128, 63, 56, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 32, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 228, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 24, 0, 0, 0, + 2, 0, 0, 0, 124, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 88, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 116, 0, 0, 0, + 1, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc new file mode 100644 index 00000000..06b9dc85 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_PSDualTextureNoFog.inc @@ -0,0 +1,170 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 zw 1 NONE float zw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xy +dcl_input_ps linear v1.zw +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.zwzz, t1.xyzw, s1 +mul r0.xyzw, r0.xyzw, v0.xyzw +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v1.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, l(2.000000, 2.000000, 2.000000, 1.000000) +mul o0.xyzw, r0.xyzw, r1.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_PSDualTextureNoFog[] = +{ + 68, 88, 66, 67, 232, 140, + 86, 233, 43, 143, 191, 22, + 102, 31, 178, 156, 60, 166, + 146, 205, 1, 0, 0, 0, + 248, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 12, 2, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 86, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 12, 12, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 56, 1, + 0, 0, 80, 0, 0, 0, + 78, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 1, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 1, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 194, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 230, 26, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 1, 0, 0, 0, + 0, 96, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 64, + 0, 0, 0, 64, 0, 0, + 0, 64, 0, 0, 128, 63, + 56, 0, 0, 7, 242, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 228, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 24, 0, 0, 0, 2, 0, + 0, 0, 124, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 1, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc new file mode 100644 index 00000000..7fd733b5 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTexture.inc @@ -0,0 +1,211 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 zw 2 NONE float zw +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[7], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o2.zw +dcl_output_siv o3.xyzw, position +mov o0.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[2].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +mov o2.zw, v2.xxxy +dp4 o3.x, v0.xyzw, cb0[3].xyzw +dp4 o3.y, v0.xyzw, cb0[4].xyzw +dp4 o3.z, v0.xyzw, cb0[5].xyzw +dp4 o3.w, v0.xyzw, cb0[6].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_VSDualTexture[] = +{ + 68, 88, 66, 67, 140, 232, + 207, 173, 189, 238, 151, 106, + 133, 153, 105, 159, 135, 205, + 242, 8, 1, 0, 0, 0, + 188, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 160, 0, 0, 0, 68, 1, + 0, 0, 208, 2, 0, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 156, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 128, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 15, 0, + 0, 0, 134, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 3, 12, + 0, 0, 134, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 12, 3, + 0, 0, 143, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 132, 1, + 0, 0, 80, 0, 1, 0, + 97, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 194, 32, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 194, 32, 16, 0, + 2, 0, 0, 0, 6, 20, + 16, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc new file mode 100644 index 00000000..9d9c223c --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureNoFog.inc @@ -0,0 +1,190 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 zw 1 NONE float zw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[7], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output o1.zw +dcl_output_siv o2.xyzw, position +mov o0.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +mov o1.zw, v2.xxxy +dp4 o2.x, v0.xyzw, cb0[3].xyzw +dp4 o2.y, v0.xyzw, cb0[4].xyzw +dp4 o2.z, v0.xyzw, cb0[5].xyzw +dp4 o2.w, v0.xyzw, cb0[6].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_VSDualTextureNoFog[] = +{ + 68, 88, 66, 67, 20, 214, + 202, 154, 189, 123, 20, 187, + 69, 15, 156, 71, 193, 40, + 204, 248, 1, 0, 0, 0, + 88, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 160, 0, 0, 0, 44, 1, + 0, 0, 108, 2, 0, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 132, 0, 0, 0, + 4, 0, 0, 0, 8, 0, + 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 12, + 0, 0, 110, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 12, 3, + 0, 0, 119, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 67, 79, 76, 79, + 82, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 83, + 86, 95, 80, 111, 115, 105, + 116, 105, 111, 110, 0, 171, + 83, 72, 69, 88, 56, 1, + 0, 0, 80, 0, 1, 0, + 78, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 194, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 6, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 194, 32, + 16, 0, 1, 0, 0, 0, + 6, 20, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 228, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 24, 0, 0, 0, 2, 0, + 0, 0, 124, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 1, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc new file mode 100644 index 00000000..9c25a500 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVc.inc @@ -0,0 +1,221 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xy 2 NONE float xy +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 zw 2 NONE float zw +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[7], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xy +dcl_input v3.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o2.zw +dcl_output_siv o3.xyzw, position +mul o0.xyzw, v3.xyzw, cb0[0].xyzw +dp4_sat o1.w, v0.xyzw, cb0[2].xyzw +mov o1.xyz, l(0,0,0,0) +mov o2.xy, v1.xyxx +mov o2.zw, v2.xxxy +dp4 o3.x, v0.xyzw, cb0[3].xyzw +dp4 o3.y, v0.xyzw, cb0[4].xyzw +dp4 o3.z, v0.xyzw, cb0[5].xyzw +dp4 o3.w, v0.xyzw, cb0[6].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_VSDualTextureVc[] = +{ + 68, 88, 66, 67, 254, 227, + 99, 148, 11, 12, 82, 218, + 221, 166, 168, 104, 7, 33, + 207, 201, 1, 0, 0, 0, + 236, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 188, 0, 0, 0, 96, 1, + 0, 0, 0, 3, 0, 0, + 73, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 125, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 134, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 12, 3, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 152, 1, 0, 0, + 80, 0, 1, 0, 102, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 194, 32, 16, 0, + 2, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 8, 114, 32, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 194, 32, 16, 0, + 2, 0, 0, 0, 6, 20, + 16, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 3, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 3, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 3, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc new file mode 100644 index 00000000..27d3dc68 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/DualTextureEffect_VSDualTextureVcNoFog.inc @@ -0,0 +1,200 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xy 2 NONE float xy +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 zw 1 NONE float zw +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[7], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xy +dcl_input v3.xyzw +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output o1.zw +dcl_output_siv o2.xyzw, position +mul o0.xyzw, v3.xyzw, cb0[0].xyzw +mov o1.xy, v1.xyxx +mov o1.zw, v2.xxxy +dp4 o2.x, v0.xyzw, cb0[3].xyzw +dp4 o2.y, v0.xyzw, cb0[4].xyzw +dp4 o2.z, v0.xyzw, cb0[5].xyzw +dp4 o2.w, v0.xyzw, cb0[6].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE DualTextureEffect_VSDualTextureVcNoFog[] = +{ + 68, 88, 66, 67, 211, 41, + 84, 141, 130, 240, 152, 3, + 75, 200, 17, 59, 116, 89, + 102, 11, 1, 0, 0, 0, + 136, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 188, 0, 0, 0, 72, 1, + 0, 0, 156, 2, 0, 0, + 73, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 125, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 132, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 110, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 12, 3, 0, 0, + 119, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 76, 1, 0, 0, + 80, 0, 1, 0, 83, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 194, 32, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 194, 32, + 16, 0, 1, 0, 0, 0, + 6, 20, 16, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 2, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 17, 0, 0, 8, + 130, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 228, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 24, 0, 0, 0, 2, 0, + 0, 0, 124, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 1, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc new file mode 100644 index 00000000..9f9c8282 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMap.inc @@ -0,0 +1,203 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[12], immediateIndexed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texturecube (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xy +dcl_input_ps linear v3.xyz +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texturecube)(float,float,float,float) r0.xyz, v3.xyzx, t1.xyzw, s1 +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v2.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, v0.xyzw +mad r0.xyz, r0.xyzx, r1.wwww, -r1.xyzx +mad r0.xyz, v1.xyzx, r0.xyzx, r1.xyzx +mad r1.xyz, cb0[11].xyzx, r1.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r1.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_PSEnvMap[] = +{ + 68, 88, 66, 67, 157, 9, + 99, 156, 11, 99, 91, 141, + 218, 79, 141, 114, 94, 69, + 126, 40, 1, 0, 0, 0, + 152, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 172, 2, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 110, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 7, 7, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 192, 1, + 0, 0, 80, 0, 0, 0, + 112, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 1, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 88, 48, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 1, 0, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 98, 16, 0, 3, + 114, 16, 16, 0, 3, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 69, 0, + 0, 139, 130, 1, 0, 128, + 67, 85, 21, 0, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 3, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 1, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 32, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc new file mode 100644 index 00000000..d856e545 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapNoFog.inc @@ -0,0 +1,184 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texturecube (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_input_ps linear v2.xy +dcl_input_ps linear v3.xyz +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texturecube)(float,float,float,float) r0.xyz, v3.xyzx, t1.xyzw, s1 +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v2.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, v0.xyzw +mad r0.xyz, r0.xyzx, r1.wwww, -r1.xyzx +mad o0.xyz, v1.xyzx, r0.xyzx, r1.xyzx +mov o0.w, r1.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_PSEnvMapNoFog[] = +{ + 68, 88, 66, 67, 69, 131, + 102, 255, 198, 7, 8, 191, + 110, 207, 207, 220, 90, 166, + 34, 61, 1, 0, 0, 0, + 56, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 76, 2, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 7, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 110, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 7, 7, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 96, 1, + 0, 0, 80, 0, 0, 0, + 88, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 1, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 88, 48, 0, 4, 0, 112, + 16, 0, 1, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 98, 16, + 0, 3, 114, 16, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 130, 1, + 0, 128, 67, 85, 21, 0, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 3, 0, 0, 0, 70, 126, + 16, 0, 1, 0, 0, 0, + 0, 96, 16, 0, 1, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc new file mode 100644 index 00000000..5a6655aa --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecular.inc @@ -0,0 +1,216 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[12], immediateIndexed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texturecube (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xy +dcl_input_ps linear v3.xyz +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texturecube)(float,float,float,float) r0.xyzw, v3.xyzx, t1.xyzw, s1 +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v2.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, v0.xyzw +mad r0.xyz, r0.xyzx, r1.wwww, -r1.xyzx +mul r0.w, r0.w, r1.w +mad r0.xyz, v1.xyzx, r0.xyzx, r1.xyzx +mad r0.xyz, cb0[0].xyzx, r0.wwww, r0.xyzx +mad r1.xyz, cb0[11].xyzx, r1.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r1.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_PSEnvMapSpecular[] = +{ + 68, 88, 66, 67, 3, 3, + 118, 118, 47, 120, 137, 76, + 211, 129, 169, 16, 12, 223, + 109, 239, 1, 0, 0, 0, + 220, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 240, 2, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 110, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 7, 7, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 4, 2, + 0, 0, 80, 0, 0, 0, + 129, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 1, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 88, 48, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 1, 0, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 98, 16, 0, 3, + 114, 16, 16, 0, 3, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 69, 0, + 0, 139, 130, 1, 0, 128, + 67, 85, 21, 0, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 3, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 1, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 31, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 228, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 24, 0, 0, 0, 2, 0, + 0, 0, 124, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 1, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc new file mode 100644 index 00000000..c74bd04f --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_PSEnvMapSpecularNoFog.inc @@ -0,0 +1,201 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[1], immediateIndexed +dcl_sampler s0, mode_default +dcl_sampler s1, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texturecube (float,float,float,float) t1 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_input_ps linear v2.xy +dcl_input_ps linear v3.xyz +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texturecube)(float,float,float,float) r0.xyzw, v3.xyzx, t1.xyzw, s1 +sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v2.xyxx, t0.xyzw, s0 +mul r1.xyzw, r1.xyzw, v0.xyzw +mad r0.xyz, r0.xyzx, r1.wwww, -r1.xyzx +mul r0.w, r0.w, r1.w +mad r0.xyz, v1.xyzx, r0.xyzx, r1.xyzx +mov o0.w, r1.w +mad o0.xyz, cb0[0].xyzx, r0.wwww, r0.xyzx +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_PSEnvMapSpecularNoFog[] = +{ + 68, 88, 66, 67, 169, 57, + 65, 205, 202, 70, 74, 80, + 98, 117, 65, 126, 198, 71, + 210, 186, 1, 0, 0, 0, + 140, 3, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 160, 2, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 7, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 110, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 7, 7, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 180, 1, + 0, 0, 80, 0, 0, 0, + 109, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 1, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 88, 48, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 98, 16, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 98, 16, 0, 3, + 114, 16, 16, 0, 3, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 69, 0, + 0, 139, 130, 1, 0, 128, + 67, 85, 21, 0, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 3, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 1, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 10, 114, 32, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc new file mode 100644 index 00000000..5436f553 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMap.inc @@ -0,0 +1,377 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[24], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o3.xyz +dcl_output_siv o4.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[17].xyzx +dp3 r0.y, v1.xyzx, cb0[18].xyzx +dp3 r0.z, v1.xyzx, cb0[19].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[4].xyzx, r0.xyzx +dp3 r1.y, -cb0[5].xyzx, r0.xyzx +dp3 r1.z, -cb0[6].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r2.xyz, r1.yyyy, cb0[8].xyzx +mad r1.xyw, r1.xxxx, cb0[7].xyxz, r2.xyxz +mad r1.xyz, r1.zzzz, cb0[9].xyzx, r1.xywx +mad o0.xyz, r1.xyzx, cb0[2].xyzx, cb0[3].xyzx +mov o0.w, cb0[2].w +dp4_sat o1.w, v0.xyzw, cb0[12].xyzw +mov o1.xyz, cb0[1].xxxx +mov o2.xy, v2.xyxx +dp4 r1.x, v0.xyzw, cb0[13].xyzw +dp4 r1.y, v0.xyzw, cb0[14].xyzw +dp4 r1.z, v0.xyzw, cb0[15].xyzw +add r1.xyz, -r1.xyzx, cb0[10].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r0.w, -r1.xyzx, r0.xyzx +add r0.w, r0.w, r0.w +mad o3.xyz, r0.xyzx, -r0.wwww, -r1.xyzx +dp4 o4.x, v0.xyzw, cb0[20].xyzw +dp4 o4.y, v0.xyzw, cb0[21].xyzw +dp4 o4.z, v0.xyzw, cb0[22].xyzw +dp4 o4.w, v0.xyzw, cb0[23].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_VSEnvMap[] = +{ + 68, 88, 66, 67, 131, 31, + 168, 141, 23, 224, 53, 49, + 50, 52, 102, 39, 187, 242, + 82, 62, 1, 0, 0, 0, + 4, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 72, 1, + 0, 0, 24, 6, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 134, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 7, 8, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 200, 4, 0, 0, + 80, 0, 1, 0, 50, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 3, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 3, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 18, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 70, 8, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 1, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 3, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 54, 0, + 0, 6, 114, 32, 16, 0, + 1, 0, 0, 0, 6, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 32, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 17, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 17, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc new file mode 100644 index 00000000..79f4622b --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapFresnel.inc @@ -0,0 +1,411 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[24], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o3.xyz +dcl_output_siv o4.xyzw, position +dcl_temps 3 +dp3 r0.x, v1.xyzx, cb0[17].xyzx +dp3 r0.y, v1.xyzx, cb0[18].xyzx +dp3 r0.z, v1.xyzx, cb0[19].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.x, -cb0[4].xyzx, r0.xyzx +dp3 r1.y, -cb0[5].xyzx, r0.xyzx +dp3 r1.z, -cb0[6].xyzx, r0.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r1.xyz, r1.xyzx, r2.xyzx +mul r2.xyz, r1.yyyy, cb0[8].xyzx +mad r1.xyw, r1.xxxx, cb0[7].xyxz, r2.xyxz +mad r1.xyz, r1.zzzz, cb0[9].xyzx, r1.xywx +mad o0.xyz, r1.xyzx, cb0[2].xyzx, cb0[3].xyzx +mov o0.w, cb0[2].w +dp4 r1.x, v0.xyzw, cb0[13].xyzw +dp4 r1.y, v0.xyzw, cb0[14].xyzw +dp4 r1.z, v0.xyzw, cb0[15].xyzw +add r1.xyz, -r1.xyzx, cb0[10].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r0.w, r1.xyzx, r0.xyzx +add r0.w, -|r0.w|, l(1.000000) +max r0.w, r0.w, l(0.000000) +log r0.w, r0.w +mul r0.w, r0.w, cb0[1].y +exp r0.w, r0.w +mul o1.xyz, r0.wwww, cb0[1].xxxx +dp4_sat o1.w, v0.xyzw, cb0[12].xyzw +mov o2.xy, v2.xyxx +dp3 r0.w, -r1.xyzx, r0.xyzx +add r0.w, r0.w, r0.w +mad o3.xyz, r0.xyzx, -r0.wwww, -r1.xyzx +dp4 o4.x, v0.xyzw, cb0[20].xyzw +dp4 o4.y, v0.xyzw, cb0[21].xyzw +dp4 o4.z, v0.xyzw, cb0[22].xyzw +dp4 o4.w, v0.xyzw, cb0[23].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_VSEnvMapFresnel[] = +{ + 68, 88, 66, 67, 71, 172, + 126, 31, 77, 105, 250, 80, + 172, 118, 91, 20, 70, 100, + 127, 147, 1, 0, 0, 0, + 172, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 72, 1, + 0, 0, 192, 6, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 134, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 7, 8, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 112, 5, 0, 0, + 80, 0, 1, 0, 92, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 3, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 3, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 18, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 70, 8, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 1, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 3, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 128, 193, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 52, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 47, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 25, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 17, 0, 0, 8, 18, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 228, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 24, 0, + 0, 0, 2, 0, 0, 0, + 124, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc new file mode 100644 index 00000000..f54dd6f1 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLight.inc @@ -0,0 +1,343 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[24], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o3.xyz +dcl_output_siv o4.xyzw, position +dcl_temps 2 +dp3 r0.x, v1.xyzx, cb0[17].xyzx +dp3 r0.y, v1.xyzx, cb0[18].xyzx +dp3 r0.z, v1.xyzx, cb0[19].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[4].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.xyz, r0.wwww, cb0[7].xyzx +mad o0.xyz, r1.xyzx, cb0[2].xyzx, cb0[3].xyzx +mov o0.w, cb0[2].w +dp4_sat o1.w, v0.xyzw, cb0[12].xyzw +mov o1.xyz, cb0[1].xxxx +mov o2.xy, v2.xyxx +dp4 r1.x, v0.xyzw, cb0[13].xyzw +dp4 r1.y, v0.xyzw, cb0[14].xyzw +dp4 r1.z, v0.xyzw, cb0[15].xyzw +add r1.xyz, -r1.xyzx, cb0[10].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r0.w, -r1.xyzx, r0.xyzx +add r0.w, r0.w, r0.w +mad o3.xyz, r0.xyzx, -r0.wwww, -r1.xyzx +dp4 o4.x, v0.xyzw, cb0[20].xyzw +dp4 o4.y, v0.xyzw, cb0[21].xyzw +dp4 o4.z, v0.xyzw, cb0[22].xyzw +dp4 o4.w, v0.xyzw, cb0[23].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_VSEnvMapOneLight[] = +{ + 68, 88, 66, 67, 215, 39, + 2, 90, 92, 167, 221, 160, + 68, 56, 185, 26, 25, 218, + 60, 249, 1, 0, 0, 0, + 84, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 72, 1, + 0, 0, 104, 5, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 134, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 7, 8, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 24, 4, 0, 0, + 80, 0, 1, 0, 6, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 3, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 18, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 54, 0, 0, 6, + 114, 32, 16, 0, 1, 0, + 0, 0, 6, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 32, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 20, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 21, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 228, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 24, 0, 0, 0, + 2, 0, 0, 0, 124, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 88, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 116, 0, 0, 0, + 1, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc new file mode 100644 index 00000000..72eb00a6 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/EnvironmentMapEffect_VSEnvMapOneLightFresnel.inc @@ -0,0 +1,377 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[24], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output o3.xyz +dcl_output_siv o4.xyzw, position +dcl_temps 2 +dp3 r0.x, v1.xyzx, cb0[17].xyzx +dp3 r0.y, v1.xyzx, cb0[18].xyzx +dp3 r0.z, v1.xyzx, cb0[19].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[4].xyzx, r0.xyzx +ge r1.x, r0.w, l(0.000000) +and r1.x, r1.x, l(0x3f800000) +mul r0.w, r0.w, r1.x +mul r1.xyz, r0.wwww, cb0[7].xyzx +mad o0.xyz, r1.xyzx, cb0[2].xyzx, cb0[3].xyzx +mov o0.w, cb0[2].w +dp4 r1.x, v0.xyzw, cb0[13].xyzw +dp4 r1.y, v0.xyzw, cb0[14].xyzw +dp4 r1.z, v0.xyzw, cb0[15].xyzw +add r1.xyz, -r1.xyzx, cb0[10].xyzx +dp3 r0.w, r1.xyzx, r1.xyzx +rsq r0.w, r0.w +mul r1.xyz, r0.wwww, r1.xyzx +dp3 r0.w, r1.xyzx, r0.xyzx +add r0.w, -|r0.w|, l(1.000000) +max r0.w, r0.w, l(0.000000) +log r0.w, r0.w +mul r0.w, r0.w, cb0[1].y +exp r0.w, r0.w +mul o1.xyz, r0.wwww, cb0[1].xxxx +dp4_sat o1.w, v0.xyzw, cb0[12].xyzw +mov o2.xy, v2.xyxx +dp3 r0.w, -r1.xyzx, r0.xyzx +add r0.w, r0.w, r0.w +mad o3.xyz, r0.xyzx, -r0.wwww, -r1.xyzx +dp4 o4.x, v0.xyzw, cb0[20].xyzw +dp4 o4.y, v0.xyzw, cb0[21].xyzw +dp4 o4.z, v0.xyzw, cb0[22].xyzw +dp4 o4.w, v0.xyzw, cb0[23].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE EnvironmentMapEffect_VSEnvMapOneLightFresnel[] = +{ + 68, 88, 66, 67, 183, 50, + 20, 91, 199, 254, 128, 97, + 48, 63, 67, 36, 199, 86, + 150, 229, 1, 0, 0, 0, + 252, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 72, 1, + 0, 0, 16, 6, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 79, 83, 71, 78, + 156, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 128, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 3, 12, 0, 0, + 134, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 7, 8, 0, 0, + 143, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 4, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 192, 4, 0, 0, + 80, 0, 1, 0, 48, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 3, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 17, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 18, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 17, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 17, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 193, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 25, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 32, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 17, 32, + 0, 8, 130, 32, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 32, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 20, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 4, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 21, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 4, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 4, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 228, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 24, 0, 0, 0, + 2, 0, 0, 0, 124, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 88, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 116, 0, 0, 0, + 1, 0, 0, 0, 68, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/GenerateMips_main.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/GenerateMips_main.inc new file mode 100644 index 00000000..09eff9e8 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/GenerateMips_main.inc @@ -0,0 +1,145 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[1], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_uav_typed_texture2d (float,float,float,float) u0 +dcl_input vThreadGroupID.xy +dcl_input vThreadIDInGroup.xy +dcl_temps 2 +dcl_thread_group 8, 8, 1 +imad r0.xyzw, vThreadGroupID.xyyy, l(8, 8, 8, 8), vThreadIDInGroup.xyyy +utof r1.xy, r0.xwxx +add r1.xy, r1.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r1.xy, r1.xyxx, cb0[0].xyxx +utof r1.z, cb0[0].z +sample_l_indexable(texture2d)(float,float,float,float) r1.xyzw, r1.xyxx, t0.xyzw, s0, r1.z +store_uav_typed u0.xyzw, r0.xyzw, r1.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE GenerateMips_main[] = +{ + 68, 88, 66, 67, 139, 43, + 171, 21, 172, 255, 118, 42, + 154, 115, 210, 228, 19, 66, + 84, 18, 1, 0, 0, 0, + 116, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 64, 0, 0, 0, 80, 0, + 0, 0, 184, 1, 0, 0, + 73, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 79, 83, + 71, 78, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 83, 72, 69, 88, + 96, 1, 0, 0, 80, 0, + 5, 0, 88, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 156, 24, 0, 4, 0, 224, + 17, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 95, 0, + 0, 2, 50, 16, 2, 0, + 95, 0, 0, 2, 50, 32, + 2, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 35, 0, 0, 10, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 21, 2, 0, + 2, 64, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 70, 37, 2, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 1, 0, 0, 0, + 198, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 10, + 50, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 70, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 0, 6, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 72, 0, 0, 141, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 164, 0, 0, 7, 242, 224, + 17, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 180, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 128, 0, 0, 0, + 62, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 108, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 20, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc new file mode 100644 index 00000000..7a03f286 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc @@ -0,0 +1,420 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xyz +dcl_input_ps linear v3.xyzw +dcl_output o0.xyzw +dcl_temps 4 +add r0.xyz, -v1.xyzx, cb0[12].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mad r1.xyz, r0.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r1.w, r1.xyzx, r1.xyzx +rsq r1.w, r1.w +mul r1.xyz, r1.wwww, r1.xyzx +dp3 r1.w, v2.xyzx, v2.xyzx +rsq r1.w, r1.w +mul r2.xyz, r1.wwww, v2.xyzx +dp3 r1.x, r1.xyzx, r2.xyzx +mad r3.xyz, r0.xyzx, r0.wwww, -cb0[4].xyzx +mad r0.xyz, r0.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul r3.xyz, r0.wwww, r3.xyzx +dp3 r1.y, r3.xyzx, r2.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r1.z, r0.xyzx, r2.xyzx +max r0.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +dp3 r1.x, -cb0[3].xyzx, r2.xyzx +dp3 r1.y, -cb0[4].xyzx, r2.xyzx +dp3 r1.z, -cb0[5].xyzx, r2.xyzx +ge r2.xyz, r1.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r2.xyz, r2.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r0.xyz, r0.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r2.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul r0.xyz, r0.xyzx, cb0[2].xyzx +sample_indexable(texture2d)(float,float,float,float) r2.xyzw, v0.xyxx, t0.xyzw, s0 +mul r2.xyzw, r2.xyzw, v3.xyzw +mul r0.xyz, r0.xyzx, r2.wwww +mul r3.xyz, r1.yyyy, cb0[7].xyzx +mad r1.xyw, r1.xxxx, cb0[6].xyxz, r3.xyxz +mad r1.xyz, r1.zzzz, cb0[8].xyzx, r1.xywx +mad r1.xyz, r1.xyzx, cb0[0].xyzx, cb0[1].xyzx +mad r0.xyz, r2.xyzx, r1.xyzx, r0.xyzx +mad r1.xyz, cb0[13].xyzx, r2.wwww, -r0.xyzx +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +mov o0.w, r2.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_PSSkinnedPixelLighting[] = +{ + 68, 88, 66, 67, 205, 238, + 143, 140, 178, 65, 203, 209, + 67, 78, 138, 68, 75, 82, + 38, 112, 1, 0, 0, 0, + 212, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 176, 0, 0, 0, 228, 0, + 0, 0, 68, 7, 0, 0, + 73, 83, 71, 78, 120, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 104, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 113, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 88, 6, + 0, 0, 80, 0, 0, 0, + 150, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 114, 16, 16, 0, + 2, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 3, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 4, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 18, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 2, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 50, 0, 0, 10, 178, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 136, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 8, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 10, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 70, 3, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 32, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc new file mode 100644 index 00000000..0033fde8 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc @@ -0,0 +1,157 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[14], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 2 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +mad r0.xyz, v1.xyzx, r0.wwww, r0.xyzx +mad r1.xyz, cb0[13].xyzx, r0.wwww, -r0.xyzx +mov o0.w, r0.w +mad o0.xyz, v1.wwww, r1.xyzx, r0.xyzx +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_PSSkinnedVertexLighting[] = +{ + 68, 88, 66, 67, 34, 223, + 3, 44, 153, 63, 227, 172, + 41, 191, 222, 82, 131, 245, + 43, 22, 1, 0, 0, 0, + 168, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 24, 2, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 15, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 68, 1, + 0, 0, 80, 0, 0, 0, + 81, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 14, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 1, 0, 0, 0, 98, 16, + 0, 3, 50, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 32, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc new file mode 100644 index 00000000..486684ec --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc @@ -0,0 +1,138 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xyz +dcl_input_ps linear v2.xy +dcl_output o0.xyzw +dcl_temps 1 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v2.xyxx, t0.xyzw, s0 +mul r0.xyzw, r0.xyzw, v0.xyzw +mad o0.xyz, v1.xyzx, r0.wwww, r0.xyzx +mov o0.w, r0.w +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_PSSkinnedVertexLightingNoFog[] = +{ + 68, 88, 66, 67, 164, 58, + 62, 66, 161, 173, 104, 194, + 104, 188, 84, 59, 140, 69, + 107, 145, 1, 0, 0, 0, + 72, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 152, 0, 0, 0, 204, 0, + 0, 0, 184, 1, 0, 0, + 73, 83, 71, 78, 96, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 80, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 7, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 228, 0, + 0, 0, 80, 0, 0, 0, + 57, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 114, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc new file mode 100644 index 00000000..7603eef7 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc @@ -0,0 +1,529 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xyzw +// BLENDWEIGHT 0 xyzw 4 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_input v4.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 4 +imul null, r0.xyzw, v3.xyzw, l(3, 3, 3, 3) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +mad r1.xyzw, cb0[r0.z + 26].xyzw, v4.zzzz, r1.xyzw +mad r1.xyzw, cb0[r0.w + 26].xyzw, v4.wwww, r1.xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 27].xyzw, v4.zzzz, r3.xyzw +mad r3.xyzw, cb0[r0.w + 27].xyzw, v4.wwww, r3.xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r3.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 28].xyzw, v4.zzzz, r3.xyzw +mad r0.xyzw, cb0[r0.w + 28].xyzw, v4.wwww, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r2.x, r0.w, l(0.000000) +and r2.x, r2.x, l(0x3f800000) +mul r0.w, r0.w, r2.x +mul r2.yzw, r0.wwww, cb0[6].xxyz +mad o0.xyz, r2.yzwy, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r3.x, r1.xyzw, cb0[15].xyzw +dp4 r3.y, r1.xyzw, cb0[16].xyzw +dp4 r3.z, r1.xyzw, cb0[17].xyzw +add r2.yzw, -r3.xxyz, cb0[12].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mad r2.yzw, r2.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mul r2.yzw, r0.wwww, r2.yyzw +dp3 r0.x, r2.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r2.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedOneLightFourBones[] = +{ + 68, 88, 66, 67, 247, 59, + 5, 109, 75, 221, 79, 216, + 220, 196, 152, 20, 92, 159, + 55, 73, 1, 0, 0, 0, + 0, 10, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 112, 9, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 236, 7, 0, 0, 80, 0, + 1, 0, 251, 1, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 17, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 28, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 226, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 2, 0, + 0, 0, 86, 14, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 150, 7, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 226, 0, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc new file mode 100644 index 00000000..4067262f --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc @@ -0,0 +1,446 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint x +// BLENDWEIGHT 0 xyzw 4 NONE float x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.x +dcl_input v4.x +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 4 +imul null, r0.x, v3.x, l(3) +mul r1.xyzw, v4.xxxx, cb0[r0.x + 26].xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.xxxx, cb0[r0.x + 27].xyzw +mul r0.xyzw, v4.xxxx, cb0[r0.x + 28].xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r2.x, r0.w, l(0.000000) +and r2.x, r2.x, l(0x3f800000) +mul r0.w, r0.w, r2.x +mul r2.yzw, r0.wwww, cb0[6].xxyz +mad o0.xyz, r2.yzwy, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r3.x, r1.xyzw, cb0[15].xyzw +dp4 r3.y, r1.xyzw, cb0[16].xyzw +dp4 r3.z, r1.xyzw, cb0[17].xyzw +add r2.yzw, -r3.xxyz, cb0[12].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mad r2.yzw, r2.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mul r2.yzw, r0.wwww, r2.yyzw +dp3 r0.x, r2.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r2.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedOneLightOneBone[] = +{ + 68, 88, 66, 67, 79, 146, + 189, 140, 61, 29, 188, 98, + 129, 101, 234, 167, 61, 250, + 30, 61, 1, 0, 0, 0, + 68, 8, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 180, 7, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 1, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 1, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 48, 6, 0, 0, 80, 0, + 1, 0, 140, 1, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 16, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 0, 0, + 0, 0, 6, 16, 16, 0, + 4, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 226, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 2, 0, + 0, 0, 86, 14, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 150, 7, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 226, 0, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc new file mode 100644 index 00000000..847abe18 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc @@ -0,0 +1,475 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xy +// BLENDWEIGHT 0 xyzw 4 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xy +dcl_input v4.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 4 +imul null, r0.xy, v3.xyxx, l(3, 3, 0, 0) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r0.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r0.w, -cb0[3].xyzx, r0.xyzx +ge r2.x, r0.w, l(0.000000) +and r2.x, r2.x, l(0x3f800000) +mul r0.w, r0.w, r2.x +mul r2.yzw, r0.wwww, cb0[6].xxyz +mad o0.xyz, r2.yzwy, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r3.x, r1.xyzw, cb0[15].xyzw +dp4 r3.y, r1.xyzw, cb0[16].xyzw +dp4 r3.z, r1.xyzw, cb0[17].xyzw +add r2.yzw, -r3.xxyz, cb0[12].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mad r2.yzw, r2.yyzw, r0.wwww, -cb0[3].xxyz +dp3 r0.w, r2.yzwy, r2.yzwy +rsq r0.w, r0.w +mul r2.yzw, r0.wwww, r2.yyzw +dp3 r0.x, r2.yzwy, r0.xyzx +max r0.x, r0.x, l(0.000000) +mul r0.x, r2.x, r0.x +log r0.x, r0.x +mul r0.x, r0.x, cb0[2].w +exp r0.x, r0.x +mul r0.xyz, r0.xxxx, cb0[9].xyzx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedOneLightTwoBones[] = +{ + 68, 88, 66, 67, 106, 23, + 95, 36, 179, 155, 36, 16, + 91, 165, 182, 252, 8, 66, + 111, 185, 1, 0, 0, 0, + 224, 8, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 80, 8, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 3, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 204, 6, 0, 0, 80, 0, + 1, 0, 179, 1, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 17, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 28, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 226, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 137, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 50, 0, + 0, 11, 114, 32, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 130, 32, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 9, + 226, 0, 16, 0, 2, 0, + 0, 0, 6, 9, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 226, 0, 16, 0, 2, 0, + 0, 0, 86, 14, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 6, 137, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 7, + 16, 0, 2, 0, 0, 0, + 150, 7, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 226, 0, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 86, 14, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 150, 7, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 47, 0, 0, 5, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 25, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc new file mode 100644 index 00000000..ed0e0564 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc @@ -0,0 +1,419 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xyzw +// BLENDWEIGHT 0 xyzw 4 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_input v4.xyzw +dcl_output o0.xy +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyzw +dcl_output_siv o4.xyzw, position +dcl_temps 4 +mov o0.xy, v2.xyxx +imul null, r0.xyzw, v3.xyzw, l(3, 3, 3, 3) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +mad r1.xyzw, cb0[r0.z + 26].xyzw, v4.zzzz, r1.xyzw +mad r1.xyzw, cb0[r0.w + 26].xyzw, v4.wwww, r1.xyzw +dp4 r2.x, v0.xyzw, r1.xyzw +dp3 r1.x, v1.xyzx, r1.xyzx +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 27].xyzw, v4.zzzz, r3.xyzw +mad r3.xyzw, cb0[r0.w + 27].xyzw, v4.wwww, r3.xyzw +dp4 r2.y, v0.xyzw, r3.xyzw +dp3 r1.y, v1.xyzx, r3.xyzx +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r3.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 28].xyzw, v4.zzzz, r3.xyzw +mad r0.xyzw, cb0[r0.w + 28].xyzw, v4.wwww, r3.xyzw +dp4 r2.z, v0.xyzw, r0.xyzw +dp3 r1.z, v1.xyzx, r0.xyzx +mov r2.w, v0.w +dp4 o1.x, r2.xyzw, cb0[15].xyzw +dp4 o1.y, r2.xyzw, cb0[16].xyzw +dp4 o1.z, r2.xyzw, cb0[17].xyzw +dp4_sat o1.w, r2.xyzw, cb0[14].xyzw +dp3 r0.x, r1.xyzx, cb0[19].xyzx +dp3 r0.y, r1.xyzx, cb0[20].xyzx +dp3 r0.z, r1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r0.xyzx +mov o3.xyz, l(1.000000,1.000000,1.000000,0) +mov o3.w, cb0[0].w +dp4 o4.x, r2.xyzw, cb0[22].xyzw +dp4 o4.y, r2.xyzw, cb0[23].xyzw +dp4 o4.z, r2.xyzw, cb0[24].xyzw +dp4 o4.w, r2.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedPixelLightingFourBones[] = +{ + 68, 88, 66, 67, 155, 128, + 143, 249, 117, 182, 54, 178, + 22, 157, 217, 95, 239, 32, + 232, 182, 1, 0, 0, 0, + 216, 7, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 148, 1, + 0, 0, 72, 7, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 156, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 12, 0, 0, 128, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 128, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 8, 0, 0, 137, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 143, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 172, 5, 0, 0, 80, 0, + 1, 0, 107, 1, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 114, 32, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 3, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 11, 0, 208, 0, 0, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 30, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 26, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 26, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 166, 26, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 26, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 27, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 27, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 166, 26, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 27, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 166, 26, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 246, 31, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 114, 32, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 32, 16, 0, + 3, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc new file mode 100644 index 00000000..949e1314 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc @@ -0,0 +1,336 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint x +// BLENDWEIGHT 0 xyzw 4 NONE float x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.x +dcl_input v4.x +dcl_output o0.xy +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyzw +dcl_output_siv o4.xyzw, position +dcl_temps 4 +mov o0.xy, v2.xyxx +imul null, r0.x, v3.x, l(3) +mul r1.xyzw, v4.xxxx, cb0[r0.x + 26].xyzw +dp4 r2.x, v0.xyzw, r1.xyzw +dp3 r1.x, v1.xyzx, r1.xyzx +mul r3.xyzw, v4.xxxx, cb0[r0.x + 27].xyzw +mul r0.xyzw, v4.xxxx, cb0[r0.x + 28].xyzw +dp4 r2.y, v0.xyzw, r3.xyzw +dp3 r1.y, v1.xyzx, r3.xyzx +dp4 r2.z, v0.xyzw, r0.xyzw +dp3 r1.z, v1.xyzx, r0.xyzx +mov r2.w, v0.w +dp4 o1.x, r2.xyzw, cb0[15].xyzw +dp4 o1.y, r2.xyzw, cb0[16].xyzw +dp4 o1.z, r2.xyzw, cb0[17].xyzw +dp4_sat o1.w, r2.xyzw, cb0[14].xyzw +dp3 r0.x, r1.xyzx, cb0[19].xyzx +dp3 r0.y, r1.xyzx, cb0[20].xyzx +dp3 r0.z, r1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r0.xyzx +mov o3.xyz, l(1.000000,1.000000,1.000000,0) +mov o3.w, cb0[0].w +dp4 o4.x, r2.xyzw, cb0[22].xyzw +dp4 o4.y, r2.xyzw, cb0[23].xyzw +dp4 o4.z, r2.xyzw, cb0[24].xyzw +dp4 o4.w, r2.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedPixelLightingOneBone[] = +{ + 68, 88, 66, 67, 85, 8, + 248, 162, 17, 213, 231, 107, + 95, 211, 244, 108, 233, 119, + 107, 74, 1, 0, 0, 0, + 28, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 148, 1, + 0, 0, 140, 5, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 1, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 1, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 156, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 12, 0, 0, 128, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 128, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 8, 0, 0, 137, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 143, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 240, 3, 0, 0, 80, 0, + 1, 0, 252, 0, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 114, 32, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 3, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 17, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 28, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 114, 32, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 32, 16, 0, + 3, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc new file mode 100644 index 00000000..94e3e311 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc @@ -0,0 +1,365 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xy +// BLENDWEIGHT 0 xyzw 4 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyz 2 NONE float xyz +// COLOR 0 xyzw 3 NONE float xyzw +// SV_Position 0 xyzw 4 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xy +dcl_input v4.xy +dcl_output o0.xy +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyzw +dcl_output_siv o4.xyzw, position +dcl_temps 4 +mov o0.xy, v2.xyxx +imul null, r0.xy, v3.xyxx, l(3, 3, 0, 0) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +dp4 r2.x, v0.xyzw, r1.xyzw +dp3 r1.x, v1.xyzx, r1.xyzx +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +dp4 r2.y, v0.xyzw, r3.xyzw +dp3 r1.y, v1.xyzx, r3.xyzx +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r0.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +dp4 r2.z, v0.xyzw, r0.xyzw +dp3 r1.z, v1.xyzx, r0.xyzx +mov r2.w, v0.w +dp4 o1.x, r2.xyzw, cb0[15].xyzw +dp4 o1.y, r2.xyzw, cb0[16].xyzw +dp4 o1.z, r2.xyzw, cb0[17].xyzw +dp4_sat o1.w, r2.xyzw, cb0[14].xyzw +dp3 r0.x, r1.xyzx, cb0[19].xyzx +dp3 r0.y, r1.xyzx, cb0[20].xyzx +dp3 r0.z, r1.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r0.xyzx +mov o3.xyz, l(1.000000,1.000000,1.000000,0) +mov o3.w, cb0[0].w +dp4 o4.x, r2.xyzw, cb0[22].xyzw +dp4 o4.y, r2.xyzw, cb0[23].xyzw +dp4 o4.z, r2.xyzw, cb0[24].xyzw +dp4 o4.w, r2.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedPixelLightingTwoBones[] = +{ + 68, 88, 66, 67, 136, 60, + 2, 50, 157, 149, 150, 225, + 43, 37, 107, 28, 64, 67, + 215, 124, 1, 0, 0, 0, + 184, 6, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 148, 1, + 0, 0, 40, 6, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 3, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 156, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 12, 0, 0, 128, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 128, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 8, 0, 0, 137, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 143, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 140, 4, 0, 0, 80, 0, + 1, 0, 35, 1, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 114, 32, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 3, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 4, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 38, 0, + 0, 11, 0, 208, 0, 0, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 26, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 17, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 27, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 86, 21, 16, 0, 4, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 6, 16, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 16, 16, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 18, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 17, 0, + 0, 8, 34, 32, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 17, 0, 0, 8, 66, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 17, 0, + 0, 0, 17, 32, 0, 8, + 130, 32, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 114, 32, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 32, 16, 0, + 3, 0, 0, 0, 58, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc new file mode 100644 index 00000000..811bb4ff --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc @@ -0,0 +1,639 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xyzw +// BLENDWEIGHT 0 xyzw 4 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xyzw +dcl_input v4.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 6 +imul null, r0.xyzw, v3.xyzw, l(3, 3, 3, 3) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +mad r1.xyzw, cb0[r0.z + 26].xyzw, v4.zzzz, r1.xyzw +mad r1.xyzw, cb0[r0.w + 26].xyzw, v4.wwww, r1.xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 27].xyzw, v4.zzzz, r3.xyzw +mad r3.xyzw, cb0[r0.w + 27].xyzw, v4.wwww, r3.xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r3.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +mad r3.xyzw, cb0[r0.z + 28].xyzw, v4.zzzz, r3.xyzw +mad r0.xyzw, cb0[r0.w + 28].xyzw, v4.wwww, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r2.x, -cb0[3].xyzx, r0.xyzx +dp3 r2.y, -cb0[4].xyzx, r0.xyzx +dp3 r2.z, -cb0[5].xyzx, r0.xyzx +ge r3.xyz, r2.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r3.xyz, r3.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r2.xyz, r2.xyzx, r3.xyzx +mul r4.xyz, r2.yyyy, cb0[7].xyzx +mad r2.xyw, r2.xxxx, cb0[6].xyxz, r4.xyxz +mad r2.xyz, r2.zzzz, cb0[8].xyzx, r2.xywx +mad o0.xyz, r2.xyzx, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r2.x, r1.xyzw, cb0[15].xyzw +dp4 r2.y, r1.xyzw, cb0[16].xyzw +dp4 r2.z, r1.xyzw, cb0[17].xyzw +add r2.xyz, -r2.xyzx, cb0[12].xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mad r4.xyz, r2.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r2.w, r4.xyzx, r4.xyzx +rsq r2.w, r2.w +mul r4.xyz, r2.wwww, r4.xyzx +dp3 r4.x, r4.xyzx, r0.xyzx +mad r5.xyz, r2.xyzx, r0.wwww, -cb0[4].xyzx +mad r2.xyz, r2.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r5.xyzx, r5.xyzx +rsq r0.w, r0.w +mul r5.xyz, r0.wwww, r5.xyzx +dp3 r4.y, r5.xyzx, r0.xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, r2.xyzx +dp3 r4.z, r2.xyzx, r0.xyzx +max r0.xyz, r4.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r3.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedVertexLightingFourBones[] = +{ + 68, 88, 66, 67, 252, 39, + 215, 100, 48, 56, 40, 65, + 206, 101, 134, 130, 186, 146, + 201, 118, 1, 0, 0, 0, + 52, 12, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 164, 11, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 15, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 32, 10, 0, 0, 80, 0, + 1, 0, 136, 2, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 6, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 17, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 28, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 166, 26, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 246, 31, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 2, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 8, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 70, 3, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 16, 16, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc new file mode 100644 index 00000000..bc6bd04e --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc @@ -0,0 +1,556 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint x +// BLENDWEIGHT 0 xyzw 4 NONE float x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.x +dcl_input v4.x +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 6 +imul null, r0.x, v3.x, l(3) +mul r1.xyzw, v4.xxxx, cb0[r0.x + 26].xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.xxxx, cb0[r0.x + 27].xyzw +mul r0.xyzw, v4.xxxx, cb0[r0.x + 28].xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r2.x, -cb0[3].xyzx, r0.xyzx +dp3 r2.y, -cb0[4].xyzx, r0.xyzx +dp3 r2.z, -cb0[5].xyzx, r0.xyzx +ge r3.xyz, r2.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r3.xyz, r3.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r2.xyz, r2.xyzx, r3.xyzx +mul r4.xyz, r2.yyyy, cb0[7].xyzx +mad r2.xyw, r2.xxxx, cb0[6].xyxz, r4.xyxz +mad r2.xyz, r2.zzzz, cb0[8].xyzx, r2.xywx +mad o0.xyz, r2.xyzx, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r2.x, r1.xyzw, cb0[15].xyzw +dp4 r2.y, r1.xyzw, cb0[16].xyzw +dp4 r2.z, r1.xyzw, cb0[17].xyzw +add r2.xyz, -r2.xyzx, cb0[12].xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mad r4.xyz, r2.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r2.w, r4.xyzx, r4.xyzx +rsq r2.w, r2.w +mul r4.xyz, r2.wwww, r4.xyzx +dp3 r4.x, r4.xyzx, r0.xyzx +mad r5.xyz, r2.xyzx, r0.wwww, -cb0[4].xyzx +mad r2.xyz, r2.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r5.xyzx, r5.xyzx +rsq r0.w, r0.w +mul r5.xyz, r0.wwww, r5.xyzx +dp3 r4.y, r5.xyzx, r0.xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, r2.xyzx +dp3 r4.z, r2.xyzx, r0.xyzx +max r0.xyz, r4.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r3.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedVertexLightingOneBone[] = +{ + 68, 88, 66, 67, 171, 181, + 234, 46, 5, 98, 131, 128, + 181, 232, 74, 29, 94, 203, + 101, 251, 1, 0, 0, 0, + 120, 10, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 232, 9, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 1, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 1, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 100, 8, 0, 0, 80, 0, + 1, 0, 25, 2, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 18, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 6, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 16, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 10, + 242, 0, 16, 0, 0, 0, + 0, 0, 6, 16, 16, 0, + 4, 0, 0, 0, 70, 142, + 32, 6, 0, 0, 0, 0, + 28, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 17, 0, + 0, 7, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 2, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 8, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 70, 3, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 16, 16, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc new file mode 100644 index 00000000..e139f6a9 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc @@ -0,0 +1,585 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 NONE float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// TEXCOORD 0 xy 2 NONE float xy +// BLENDINDICES 0 xyzw 3 NONE uint xy +// BLENDWEIGHT 0 xyzw 4 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// COLOR 1 xyzw 1 NONE float xyzw +// TEXCOORD 0 xy 2 NONE float xy +// SV_Position 0 xyzw 3 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[242], dynamicIndexed +dcl_input v0.xyzw +dcl_input v1.xyz +dcl_input v2.xy +dcl_input v3.xy +dcl_input v4.xy +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xy +dcl_output_siv o3.xyzw, position +dcl_temps 6 +imul null, r0.xy, v3.xyxx, l(3, 3, 0, 0) +mul r1.xyzw, v4.yyyy, cb0[r0.y + 26].xyzw +mad r1.xyzw, cb0[r0.x + 26].xyzw, v4.xxxx, r1.xyzw +dp3 r2.x, v1.xyzx, r1.xyzx +dp4 r1.x, v0.xyzw, r1.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 27].xyzw +mad r3.xyzw, cb0[r0.x + 27].xyzw, v4.xxxx, r3.xyzw +dp3 r2.y, v1.xyzx, r3.xyzx +dp4 r1.y, v0.xyzw, r3.xyzw +mul r3.xyzw, v4.yyyy, cb0[r0.y + 28].xyzw +mad r0.xyzw, cb0[r0.x + 28].xyzw, v4.xxxx, r3.xyzw +dp3 r2.z, v1.xyzx, r0.xyzx +dp4 r1.z, v0.xyzw, r0.xyzw +dp3 r0.x, r2.xyzx, cb0[19].xyzx +dp3 r0.y, r2.xyzx, cb0[20].xyzx +dp3 r0.z, r2.xyzx, cb0[21].xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +dp3 r2.x, -cb0[3].xyzx, r0.xyzx +dp3 r2.y, -cb0[4].xyzx, r0.xyzx +dp3 r2.z, -cb0[5].xyzx, r0.xyzx +ge r3.xyz, r2.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +and r3.xyz, r3.xyzx, l(0x3f800000, 0x3f800000, 0x3f800000, 0) +mul r2.xyz, r2.xyzx, r3.xyzx +mul r4.xyz, r2.yyyy, cb0[7].xyzx +mad r2.xyw, r2.xxxx, cb0[6].xyxz, r4.xyxz +mad r2.xyz, r2.zzzz, cb0[8].xyzx, r2.xywx +mad o0.xyz, r2.xyzx, cb0[0].xyzx, cb0[1].xyzx +mov o0.w, cb0[0].w +mov r1.w, v0.w +dp4 r2.x, r1.xyzw, cb0[15].xyzw +dp4 r2.y, r1.xyzw, cb0[16].xyzw +dp4 r2.z, r1.xyzw, cb0[17].xyzw +add r2.xyz, -r2.xyzx, cb0[12].xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mad r4.xyz, r2.xyzx, r0.wwww, -cb0[3].xyzx +dp3 r2.w, r4.xyzx, r4.xyzx +rsq r2.w, r2.w +mul r4.xyz, r2.wwww, r4.xyzx +dp3 r4.x, r4.xyzx, r0.xyzx +mad r5.xyz, r2.xyzx, r0.wwww, -cb0[4].xyzx +mad r2.xyz, r2.xyzx, r0.wwww, -cb0[5].xyzx +dp3 r0.w, r5.xyzx, r5.xyzx +rsq r0.w, r0.w +mul r5.xyz, r0.wwww, r5.xyzx +dp3 r4.y, r5.xyzx, r0.xyzx +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, r2.xyzx +dp3 r4.z, r2.xyzx, r0.xyzx +max r0.xyz, r4.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mul r0.xyz, r3.xyzx, r0.xyzx +log r0.xyz, r0.xyzx +mul r0.xyz, r0.xyzx, cb0[2].wwww +exp r0.xyz, r0.xyzx +mul r2.xyz, r0.yyyy, cb0[10].xyzx +mad r0.xyw, r0.xxxx, cb0[9].xyxz, r2.xyxz +mad r0.xyz, r0.zzzz, cb0[11].xyzx, r0.xywx +mul o1.xyz, r0.xyzx, cb0[2].xyzx +dp4_sat o1.w, r1.xyzw, cb0[14].xyzw +mov o2.xy, v2.xyxx +dp4 o3.x, r1.xyzw, cb0[22].xyzw +dp4 o3.y, r1.xyzw, cb0[23].xyzw +dp4 o3.z, r1.xyzw, cb0[24].xyzw +dp4 o3.w, r1.xyzw, cb0[25].xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SkinnedEffect_VSSkinnedVertexLightingTwoBones[] = +{ + 68, 88, 66, 67, 253, 236, + 140, 3, 210, 8, 102, 44, + 105, 54, 158, 230, 216, 73, + 64, 8, 1, 0, 0, 0, + 20, 11, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 240, 0, 0, 0, 124, 1, + 0, 0, 132, 10, 0, 0, + 73, 83, 71, 78, 184, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 7, 7, 0, 0, 147, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 3, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 15, 3, 0, 0, 169, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 78, 79, + 82, 77, 65, 76, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 66, 76, 69, 78, + 68, 73, 78, 68, 73, 67, + 69, 83, 0, 66, 76, 69, + 78, 68, 87, 69, 73, 71, + 72, 84, 0, 171, 171, 171, + 79, 83, 71, 78, 132, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 104, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 110, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 3, 12, 0, 0, 119, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 83, 72, 69, 88, + 0, 9, 0, 0, 80, 0, + 1, 0, 64, 2, 0, 0, + 106, 8, 0, 1, 89, 8, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 95, 0, 0, 3, + 242, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 2, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 3, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 4, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 50, 32, 16, 0, 2, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 6, 0, + 0, 0, 38, 0, 0, 11, + 0, 208, 0, 0, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 26, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 26, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 16, 0, 0, 7, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 17, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 27, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 27, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 17, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 21, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 6, 0, 0, + 0, 0, 28, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 6, + 0, 0, 0, 0, 28, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 16, 0, 0, 7, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 17, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 19, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 20, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 9, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 86, 5, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 50, 0, + 0, 10, 178, 0, 16, 0, + 2, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 70, 136, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 70, 8, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 166, 10, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 70, 3, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 11, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 54, 0, 0, 6, + 130, 32, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 16, 16, 0, + 0, 0, 0, 0, 17, 0, + 0, 8, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 17, 0, 0, 8, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 17, 0, 0, 8, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 16, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 68, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 16, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 11, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 68, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 16, 0, + 0, 7, 34, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 68, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 16, 0, 0, 7, 66, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 47, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 50, 0, 0, 10, + 178, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 136, + 32, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 70, 8, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 114, 0, + 16, 0, 0, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 32, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 32, 0, 8, 130, 32, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 14, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 2, 0, 0, 0, 17, 0, + 0, 8, 18, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 22, 0, 0, 0, + 17, 0, 0, 8, 34, 32, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 23, 0, + 0, 0, 17, 0, 0, 8, + 66, 32, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 24, 0, 0, 0, 17, 0, + 0, 8, 130, 32, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 62, 0, 0, 1, 82, 84, + 83, 48, 136, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 24, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 76, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc new file mode 100644 index 00000000..1600f6d7 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpritePixelShader.inc @@ -0,0 +1,118 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xyzw +dcl_input_ps linear v1.xy +dcl_output o0.xyzw +dcl_temps 1 +sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.xyxx, t0.xyzw, s0 +mul o0.xyzw, r0.xyzw, v0.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SpriteEffect_SpritePixelShader[] = +{ + 68, 88, 66, 67, 139, 129, + 110, 56, 73, 191, 71, 92, + 53, 195, 34, 82, 243, 212, + 243, 147, 1, 0, 0, 0, + 236, 1, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 128, 0, 0, 0, 180, 0, + 0, 0, 92, 1, 0, 0, + 73, 83, 71, 78, 72, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 160, 0, + 0, 0, 80, 0, 0, 0, + 40, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 0, 0, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 82, 84, 83, 48, 136, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 24, 0, + 0, 0, 1, 0, 0, 0, + 84, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 76, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 127, 127, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc b/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc new file mode 100644 index 00000000..a16ed61d --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc @@ -0,0 +1,169 @@ +#if 0 +// +// Generated by Microsoft (R) D3D Shader Disassembler +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// COLOR 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// SV_Position 0 xyzw 2 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[4], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output o0.xyzw +dcl_output o1.xy +dcl_output_siv o2.xyzw, position +dcl_temps 1 +mov o0.xyzw, v0.xyzw +mov o1.xy, v1.xyxx +mul r0.xyzw, v2.yyyy, cb0[1].xyzw +mad r0.xyzw, v2.xxxx, cb0[0].xyzw, r0.xyzw +mad r0.xyzw, v2.zzzz, cb0[2].xyzw, r0.xyzw +mad o2.xyzw, v2.wwww, cb0[3].xyzw, r0.xyzw +ret +// Approximately 0 instruction slots used +#endif + +const BYTE SpriteEffect_SpriteVertexShader[] = +{ + 68, 88, 66, 67, 37, 58, + 176, 11, 214, 165, 86, 72, + 235, 236, 218, 113, 26, 203, + 253, 51, 1, 0, 0, 0, + 228, 2, 0, 0, 4, 0, + 0, 0, 48, 0, 0, 0, + 164, 0, 0, 0, 24, 1, + 0, 0, 84, 2, 0, 0, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 95, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 67, 79, + 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 111, + 115, 105, 116, 105, 111, 110, + 0, 171, 79, 83, 71, 78, + 108, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 86, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 95, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 67, 79, 76, 79, 82, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 83, 72, + 69, 88, 52, 1, 0, 0, + 80, 0, 1, 0, 77, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 0, 0, 0, 0, 95, 0, + 0, 3, 50, 16, 16, 0, + 1, 0, 0, 0, 95, 0, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 103, 0, + 0, 4, 242, 32, 16, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 8, + 242, 0, 16, 0, 0, 0, + 0, 0, 86, 21, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 50, 0, + 0, 10, 242, 0, 16, 0, + 0, 0, 0, 0, 6, 16, + 16, 0, 2, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 10, + 242, 0, 16, 0, 0, 0, + 0, 0, 166, 26, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 242, 32, + 16, 0, 2, 0, 0, 0, + 246, 31, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 82, 84, 83, 48, + 136, 0, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 48, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 127, 127, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/Kits/DirectXTK12/Src/Shaders/DualTextureEffect.fx b/Kits/DirectXTK12/Src/Shaders/DualTextureEffect.fx new file mode 100644 index 00000000..87a5c9f3 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/DualTextureEffect.fx @@ -0,0 +1,126 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +Texture2D Texture : register(t0); +Texture2D Texture2 : register(t1); + +sampler Sampler : register(s0); +sampler Sampler2 : register(s1); + + +cbuffer Parameters : register(b0) +{ + float4 DiffuseColor : packoffset(c0); + float3 FogColor : packoffset(c1); + float4 FogVector : packoffset(c2); + float4x4 WorldViewProj : packoffset(c3); +}; + + +#include "Structures.fxh" +#include "RootSig.fxh" +#include "Common.fxh" + + +// Vertex shader: basic. +[RootSignature(DualTextureRS)] +VSOutputTx2 VSDualTexture(VSInputTx2 vin) +{ + VSOutputTx2 vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.TexCoord2 = vin.TexCoord2; + + return vout; +} + + +// Vertex shader: no fog. +[RootSignature(DualTextureRS)] +VSOutputTx2NoFog VSDualTextureNoFog(VSInputTx2 vin) +{ + VSOutputTx2NoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + vout.TexCoord2 = vin.TexCoord2; + + return vout; +} + + +// Vertex shader: vertex color. +[RootSignature(DualTextureRS)] +VSOutputTx2 VSDualTextureVc(VSInputTx2Vc vin) +{ + VSOutputTx2 vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + vout.TexCoord2 = vin.TexCoord2; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Vertex shader: vertex color, no fog. +[RootSignature(DualTextureRS)] +VSOutputTx2NoFog VSDualTextureVcNoFog(VSInputTx2Vc vin) +{ + VSOutputTx2NoFog vout; + + CommonVSOutput cout = ComputeCommonVSOutput(vin.Position); + SetCommonVSOutputParamsNoFog; + + vout.TexCoord = vin.TexCoord; + vout.TexCoord2 = vin.TexCoord2; + vout.Diffuse *= vin.Color; + + return vout; +} + + +// Pixel shader: basic. +[RootSignature(DualTextureRS)] +float4 PSDualTexture(PSInputTx2 pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord); + float4 overlay = Texture2.Sample(Sampler2, pin.TexCoord2); + + color.rgb *= 2; + color *= overlay * pin.Diffuse; + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: no fog. +[RootSignature(DualTextureRS)] +float4 PSDualTextureNoFog(PSInputTx2NoFog pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord); + float4 overlay = Texture2.Sample(Sampler2, pin.TexCoord2); + + color.rgb *= 2; + color *= overlay * pin.Diffuse; + + return color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/EnvironmentMapEffect.fx b/Kits/DirectXTK12/Src/Shaders/EnvironmentMapEffect.fx new file mode 100644 index 00000000..96868370 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/EnvironmentMapEffect.fx @@ -0,0 +1,175 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +Texture2D Texture : register(t0); +TextureCube EnvironmentMap : register(t1); + +sampler Sampler : register(s0); +sampler EnvMapSampler : register(s1); + + +cbuffer Parameters : register(b0) +{ + float3 EnvironmentMapSpecular : packoffset(c0); + float EnvironmentMapAmount : packoffset(c1.x); + float FresnelFactor : packoffset(c1.y); + + float4 DiffuseColor : packoffset(c2); + float3 EmissiveColor : packoffset(c3); + + float3 LightDirection[3] : packoffset(c4); + float3 LightDiffuseColor[3] : packoffset(c7); + + float3 EyePosition : packoffset(c10); + + float3 FogColor : packoffset(c11); + float4 FogVector : packoffset(c12); + + float4x4 World : packoffset(c13); + float3x3 WorldInverseTranspose : packoffset(c17); + float4x4 WorldViewProj : packoffset(c20); +}; + + +// We don't use these parameters, but Lighting.fxh won't compile without them. +#define SpecularPower 0 +#define SpecularColor 0 +#define LightSpecularColor float3(0, 0, 0) + + +#include "Structures.fxh" +#include "Common.fxh" +#include "RootSig.fxh" +#include "Lighting.fxh" + + +float ComputeFresnelFactor(float3 eyeVector, float3 worldNormal) +{ + float viewAngle = dot(eyeVector, worldNormal); + + return pow(max(1 - abs(viewAngle), 0), FresnelFactor) * EnvironmentMapAmount; +} + + +VSOutputTxEnvMap ComputeEnvMapVSOutput(VSInputNmTx vin, uniform bool useFresnel, uniform int numLights) +{ + VSOutputTxEnvMap vout; + + float4 pos_ws = mul(vin.Position, World); + float3 eyeVector = normalize(EyePosition - pos_ws.xyz); + float3 worldNormal = normalize(mul(vin.Normal, WorldInverseTranspose)); + + ColorPair lightResult = ComputeLights(eyeVector, worldNormal, numLights); + + vout.PositionPS = mul(vin.Position, WorldViewProj); + vout.Diffuse = float4(lightResult.Diffuse, DiffuseColor.a); + + if (useFresnel) + vout.Specular.rgb = ComputeFresnelFactor(eyeVector, worldNormal); + else + vout.Specular.rgb = EnvironmentMapAmount; + + vout.Specular.a = ComputeFogFactor(vin.Position); + vout.TexCoord = vin.TexCoord; + vout.EnvCoord = reflect(-eyeVector, worldNormal); + + return vout; +} + + +// Vertex shader: basic. +[RootSignature(DualTextureRS)] +VSOutputTxEnvMap VSEnvMap(VSInputNmTx vin) +{ + return ComputeEnvMapVSOutput(vin, false, 3); +} + + +// Vertex shader: fresnel. +[RootSignature(DualTextureRS)] +VSOutputTxEnvMap VSEnvMapFresnel(VSInputNmTx vin) +{ + return ComputeEnvMapVSOutput(vin, true, 3); +} + + +// Vertex shader: one light. +[RootSignature(DualTextureRS)] +VSOutputTxEnvMap VSEnvMapOneLight(VSInputNmTx vin) +{ + return ComputeEnvMapVSOutput(vin, false, 1); +} + + +// Vertex shader: one light, fresnel. +[RootSignature(DualTextureRS)] +VSOutputTxEnvMap VSEnvMapOneLightFresnel(VSInputNmTx vin) +{ + return ComputeEnvMapVSOutput(vin, true, 1); +} + + +// Pixel shader: basic. +[RootSignature(DualTextureRS)] +float4 PSEnvMap(PSInputTxEnvMap pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + float4 envmap = EnvironmentMap.Sample(EnvMapSampler, pin.EnvCoord) * color.a; + + color.rgb = lerp(color.rgb, envmap.rgb, pin.Specular.rgb); + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: no fog. +[RootSignature(DualTextureRS)] +float4 PSEnvMapNoFog(PSInputTxEnvMap pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + float4 envmap = EnvironmentMap.Sample(EnvMapSampler, pin.EnvCoord) * color.a; + + color.rgb = lerp(color.rgb, envmap.rgb, pin.Specular.rgb); + + return color; +} + + +// Pixel shader: specular. +[RootSignature(DualTextureRS)] +float4 PSEnvMapSpecular(PSInputTxEnvMap pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + float4 envmap = EnvironmentMap.Sample(EnvMapSampler, pin.EnvCoord) * color.a; + + color.rgb = lerp(color.rgb, envmap.rgb, pin.Specular.rgb); + color.rgb += EnvironmentMapSpecular * envmap.a; + + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: specular, no fog. +[RootSignature(DualTextureRS)] +float4 PSEnvMapSpecularNoFog(PSInputTxEnvMap pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + float4 envmap = EnvironmentMap.Sample(EnvMapSampler, pin.EnvCoord) * color.a; + + color.rgb = lerp(color.rgb, envmap.rgb, pin.Specular.rgb); + color.rgb += EnvironmentMapSpecular * envmap.a; + + return color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/GenerateMips.hlsl b/Kits/DirectXTK12/Src/Shaders/GenerateMips.hlsl new file mode 100644 index 00000000..72b76dac --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/GenerateMips.hlsl @@ -0,0 +1,37 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + +#include "Structures.fxh" +#include "RootSig.fxh" + +SamplerState Sampler : register(s0); +Texture2D SrcMip : register(t0); +RWTexture2D OutMip : register(u0); + +cbuffer MipConstants : register(b0) +{ + float2 InvOutTexelSize; // texel size for OutMip (NOT SrcMip) + uint SrcMipIndex; +} + +float4 Mip(uint2 coord) +{ + float2 uv = (coord.xy + 0.5) * InvOutTexelSize; + return SrcMip.SampleLevel(Sampler, uv, SrcMipIndex); +} + +[RootSignature(GenerateMipsRS)] +// Workaround for NVidia bug: some driver versions don't handle SV_DispatchThreadID correctly. +[numthreads(8, 8, 1)] +void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) +{ + uint3 DTid = Gid * uint3(8,8,1) + GTid; + OutMip[DTid.xy] = Mip(DTid.xy); +} diff --git a/Kits/DirectXTK12/Src/Shaders/Lighting.fxh b/Kits/DirectXTK12/Src/Shaders/Lighting.fxh new file mode 100644 index 00000000..d5b8452c --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Lighting.fxh @@ -0,0 +1,97 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +struct ColorPair +{ + float3 Diffuse; + float3 Specular; +}; + + +ColorPair ComputeLights(float3 eyeVector, float3 worldNormal, uniform int numLights) +{ + float3x3 lightDirections = 0; + float3x3 lightDiffuse = 0; + float3x3 lightSpecular = 0; + float3x3 halfVectors = 0; + + [unroll] + for (int i = 0; i < numLights; i++) + { + lightDirections[i] = LightDirection[i]; + lightDiffuse[i] = LightDiffuseColor[i]; + lightSpecular[i] = LightSpecularColor[i]; + + halfVectors[i] = normalize(eyeVector - lightDirections[i]); + } + + float3 dotL = mul(-lightDirections, worldNormal); + float3 dotH = mul(halfVectors, worldNormal); + + float3 zeroL = step(0, dotL); + + float3 diffuse = zeroL * dotL; + float3 specular = pow(max(dotH, 0) * zeroL, SpecularPower); + + ColorPair result; + + result.Diffuse = mul(diffuse, lightDiffuse) * DiffuseColor.rgb + EmissiveColor; + result.Specular = mul(specular, lightSpecular) * SpecularColor; + + return result; +} + + +CommonVSOutput ComputeCommonVSOutputWithLighting(float4 position, float3 normal, uniform int numLights) +{ + CommonVSOutput vout; + + float4 pos_ws = mul(position, World); + float3 eyeVector = normalize(EyePosition - pos_ws.xyz); + float3 worldNormal = normalize(mul(normal, WorldInverseTranspose)); + + ColorPair lightResult = ComputeLights(eyeVector, worldNormal, numLights); + + vout.Pos_ps = mul(position, WorldViewProj); + vout.Diffuse = float4(lightResult.Diffuse, DiffuseColor.a); + vout.Specular = lightResult.Specular; + vout.FogFactor = ComputeFogFactor(position); + + return vout; +} + + +struct CommonVSOutputPixelLighting +{ + float4 Pos_ps; + float3 Pos_ws; + float3 Normal_ws; + float FogFactor; +}; + + +CommonVSOutputPixelLighting ComputeCommonVSOutputPixelLighting(float4 position, float3 normal) +{ + CommonVSOutputPixelLighting vout; + + vout.Pos_ps = mul(position, WorldViewProj); + vout.Pos_ws = mul(position, World).xyz; + vout.Normal_ws = normalize(mul(normal, WorldInverseTranspose)); + vout.FogFactor = ComputeFogFactor(position); + + return vout; +} + + +#define SetCommonVSOutputParamsPixelLighting \ + vout.PositionPS = cout.Pos_ps; \ + vout.PositionWS = float4(cout.Pos_ws, cout.FogFactor); \ + vout.NormalWS = cout.Normal_ws; diff --git a/Kits/DirectXTK12/Src/Shaders/RootSig.fxh b/Kits/DirectXTK12/Src/Shaders/RootSig.fxh new file mode 100644 index 00000000..2693580d --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/RootSig.fxh @@ -0,0 +1,44 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 + +// Root signatures must match definition in each effect, or shaders will be recompiled on Xbox when PSO loads +#define MainRS \ +"RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ +" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ +" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ +" DENY_HULL_SHADER_ROOT_ACCESS )," \ +"DescriptorTable ( SRV(t0) ),"\ +"CBV(b0)," \ +"StaticSampler(s0)" + +#define DualTextureRS \ +"RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ +" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ +" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ +" DENY_HULL_SHADER_ROOT_ACCESS )," \ +"DescriptorTable ( SRV(t0) )," \ +"DescriptorTable ( SRV(t1) )," \ +"CBV(b0)," \ +"StaticSampler(s0)," \ +"StaticSampler(s1)" + +#define GenerateMipsRS \ +"RootFlags ( DENY_VERTEX_SHADER_ROOT_ACCESS |" \ +" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ +" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ +" DENY_HULL_SHADER_ROOT_ACCESS |" \ +" DENY_PIXEL_SHADER_ROOT_ACCESS )," \ +"RootConstants(num32BitConstants=3, b0)," \ +"DescriptorTable ( SRV(t0) )," \ +"DescriptorTable ( UAV(u0) )," \ +"StaticSampler(s0,"\ +" filter = FILTER_MIN_MAG_LINEAR_MIP_POINT,"\ +" addressU = TEXTURE_ADDRESS_CLAMP,"\ +" addressV = TEXTURE_ADDRESS_CLAMP,"\ +" addressW = TEXTURE_ADDRESS_CLAMP )" diff --git a/Kits/DirectXTK12/Src/Shaders/SkinnedEffect.fx b/Kits/DirectXTK12/Src/Shaders/SkinnedEffect.fx new file mode 100644 index 00000000..941acb6f --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/SkinnedEffect.fx @@ -0,0 +1,259 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +Texture2D Texture : register(t0); +sampler Sampler : register(s0); + + +cbuffer Parameters : register(b0) +{ + float4 DiffuseColor : packoffset(c0); + float3 EmissiveColor : packoffset(c1); + float3 SpecularColor : packoffset(c2); + float SpecularPower : packoffset(c2.w); + + float3 LightDirection[3] : packoffset(c3); + float3 LightDiffuseColor[3] : packoffset(c6); + float3 LightSpecularColor[3] : packoffset(c9); + + float3 EyePosition : packoffset(c12); + + float3 FogColor : packoffset(c13); + float4 FogVector : packoffset(c14); + + float4x4 World : packoffset(c15); + float3x3 WorldInverseTranspose : packoffset(c19); + float4x4 WorldViewProj : packoffset(c22); + + float4x3 Bones[72] : packoffset(c26); +}; + + +#include "Structures.fxh" +#include "Common.fxh" +#include "RootSig.fxh" +#include "Lighting.fxh" + +[RootSignature(MainRS)] +void Skin(inout VSInputNmTxWeights vin, uniform int boneCount) +{ + float4x3 skinning = 0; + + [unroll] + for (int i = 0; i < boneCount; i++) + { + skinning += Bones[vin.Indices[i]] * vin.Weights[i]; + } + + vin.Position.xyz = mul(vin.Position, skinning); + vin.Normal = mul(vin.Normal, (float3x3)skinning); +} + + +// Vertex shader: vertex lighting, one bone. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedVertexLightingOneBone(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 1); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: vertex lighting, two bones. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedVertexLightingTwoBones(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 2); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: vertex lighting, four bones. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedVertexLightingFourBones(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 4); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: one light, one bone. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedOneLightOneBone(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 1); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: one light, two bones. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedOneLightTwoBones(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 2); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: one light, four bones. +[RootSignature(MainRS)] +VSOutputTx VSSkinnedOneLightFourBones(VSInputNmTxWeights vin) +{ + VSOutputTx vout; + + Skin(vin, 4); + + CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); + SetCommonVSOutputParams; + + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: pixel lighting, one bone. +[RootSignature(MainRS)] +VSOutputPixelLightingTx VSSkinnedPixelLightingOneBone(VSInputNmTxWeights vin) +{ + VSOutputPixelLightingTx vout; + + Skin(vin, 1); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: pixel lighting, two bones. +[RootSignature(MainRS)] +VSOutputPixelLightingTx VSSkinnedPixelLightingTwoBones(VSInputNmTxWeights vin) +{ + VSOutputPixelLightingTx vout; + + Skin(vin, 2); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: pixel lighting, four bones. +[RootSignature(MainRS)] +VSOutputPixelLightingTx VSSkinnedPixelLightingFourBones(VSInputNmTxWeights vin) +{ + VSOutputPixelLightingTx vout; + + Skin(vin, 4); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Pixel shader: vertex lighting. +[RootSignature(MainRS)] +float4 PSSkinnedVertexLighting(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + ApplyFog(color, pin.Specular.w); + + return color; +} + + +// Pixel shader: vertex lighting, no fog. +[RootSignature(MainRS)] +float4 PSSkinnedVertexLightingNoFog(PSInputTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + AddSpecular(color, pin.Specular.rgb); + + return color; +} + + +// Pixel shader: pixel lighting. +[RootSignature(MainRS)] +float4 PSSkinnedPixelLighting(PSInputPixelLightingTx pin) : SV_Target0 +{ + float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse; + + float3 eyeVector = normalize(EyePosition - pin.PositionWS.xyz); + float3 worldNormal = normalize(pin.NormalWS); + + ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 3); + + color.rgb *= lightResult.Diffuse; + + AddSpecular(color, lightResult.Specular); + ApplyFog(color, pin.PositionWS.w); + + return color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/SpriteEffect.fx b/Kits/DirectXTK12/Src/Shaders/SpriteEffect.fx new file mode 100644 index 00000000..946b3d99 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/SpriteEffect.fx @@ -0,0 +1,36 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + +#include "Structures.fxh" +#include "RootSig.fxh" + +Texture2D Texture : register(t0); +sampler TextureSampler : register(s0); + + +cbuffer Parameters : register(b0) +{ + row_major float4x4 MatrixTransform; +}; + +[RootSignature(MainRS)] +void SpriteVertexShader(inout float4 color : COLOR0, + inout float2 texCoord : TEXCOORD0, + inout float4 position : SV_Position) +{ + position = mul(position, MatrixTransform); +} + +[RootSignature(MainRS)] +float4 SpritePixelShader(float4 color : COLOR0, + float2 texCoord : TEXCOORD0) : SV_Target0 +{ + return Texture.Sample(TextureSampler, texCoord) * color; +} diff --git a/Kits/DirectXTK12/Src/Shaders/Structures.fxh b/Kits/DirectXTK12/Src/Shaders/Structures.fxh new file mode 100644 index 00000000..e7815b52 --- /dev/null +++ b/Kits/DirectXTK12/Src/Shaders/Structures.fxh @@ -0,0 +1,229 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +// http://create.msdn.com/en-US/education/catalog/sample/stock_effects + + +// Vertex shader input structures. + +struct VSInput +{ + float4 Position : SV_Position; +}; + +struct VSInputVc +{ + float4 Position : SV_Position; + float4 Color : COLOR; +}; + +struct VSInputTx +{ + float4 Position : SV_Position; + float2 TexCoord : TEXCOORD0; +}; + +struct VSInputTxVc +{ + float4 Position : SV_Position; + float2 TexCoord : TEXCOORD0; + float4 Color : COLOR; +}; + +struct VSInputNm +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; +}; + +struct VSInputNmVc +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float4 Color : COLOR; +}; + +struct VSInputNmTx +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; +}; + +struct VSInputNmTxVc +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; + float4 Color : COLOR; +}; + +struct VSInputTx2 +{ + float4 Position : SV_Position; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; +}; + +struct VSInputTx2Vc +{ + float4 Position : SV_Position; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; + float4 Color : COLOR; +}; + +struct VSInputNmTxWeights +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; + uint4 Indices : BLENDINDICES0; + float4 Weights : BLENDWEIGHT0; +}; + + + +// Vertex shader output structures. + +struct VSOutput +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float4 PositionPS : SV_Position; +}; + +struct VSOutputNoFog +{ + float4 Diffuse : COLOR0; + float4 PositionPS : SV_Position; +}; + +struct VSOutputTx +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; + float4 PositionPS : SV_Position; +}; + +struct VSOutputTxNoFog +{ + float4 Diffuse : COLOR0; + float2 TexCoord : TEXCOORD0; + float4 PositionPS : SV_Position; +}; + +struct VSOutputPixelLighting +{ + float4 PositionWS : TEXCOORD0; + float3 NormalWS : TEXCOORD1; + float4 Diffuse : COLOR0; + float4 PositionPS : SV_Position; +}; + +struct VSOutputPixelLightingTx +{ + float2 TexCoord : TEXCOORD0; + float4 PositionWS : TEXCOORD1; + float3 NormalWS : TEXCOORD2; + float4 Diffuse : COLOR0; + float4 PositionPS : SV_Position; +}; + +struct VSOutputTx2 +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; + float4 PositionPS : SV_Position; +}; + +struct VSOutputTx2NoFog +{ + float4 Diffuse : COLOR0; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; + float4 PositionPS : SV_Position; +}; + +struct VSOutputTxEnvMap +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; + float3 EnvCoord : TEXCOORD1; + float4 PositionPS : SV_Position; +}; + + + +// Pixel shader input structures. + +struct PSInput +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; +}; + +struct PSInputNoFog +{ + float4 Diffuse : COLOR0; +}; + +struct PSInputTx +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; +}; + +struct PSInputTxNoFog +{ + float4 Diffuse : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +struct PSInputPixelLighting +{ + float4 PositionWS : TEXCOORD0; + float3 NormalWS : TEXCOORD1; + float4 Diffuse : COLOR0; +}; + +struct PSInputPixelLightingTx +{ + float2 TexCoord : TEXCOORD0; + float4 PositionWS : TEXCOORD1; + float3 NormalWS : TEXCOORD2; + float4 Diffuse : COLOR0; +}; + +struct PSInputTx2 +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; +}; + +struct PSInputTx2NoFog +{ + float4 Diffuse : COLOR0; + float2 TexCoord : TEXCOORD0; + float2 TexCoord2 : TEXCOORD1; +}; + +struct PSInputTxEnvMap +{ + float4 Diffuse : COLOR0; + float4 Specular : COLOR1; + float2 TexCoord : TEXCOORD0; + float3 EnvCoord : TEXCOORD1; +}; diff --git a/Kits/DirectXTK12/Src/SharedResourcePool.h b/Kits/DirectXTK12/Src/SharedResourcePool.h new file mode 100644 index 00000000..459e35ca --- /dev/null +++ b/Kits/DirectXTK12/Src/SharedResourcePool.h @@ -0,0 +1,105 @@ +//-------------------------------------------------------------------------------------- +// File: SharedResourcePool.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + +#include "PlatformHelpers.h" + + +namespace DirectX +{ + // Pool manager ensures that only a single TData instance is created for each unique TKey. + // This is used to avoid duplicate resource creation, so that for instance a caller can + // create any number of SpriteBatch instances, but these can internally share shaders and + // vertex buffer if more than one SpriteBatch uses the same underlying D3D device. + template + class SharedResourcePool + { + public: + SharedResourcePool() + : mResourceMap(std::make_shared()) + { } + + SharedResourcePool(SharedResourcePool const&) = delete; + SharedResourcePool& operator= (SharedResourcePool const&) = delete; + + // Allocates or looks up the shared TData instance for the specified key. + std::shared_ptr DemandCreate(TKey key, TConstructorArgs... args) + { + std::lock_guard lock(mResourceMap->mutex); + + // Return an existing instance? + auto pos = mResourceMap->find(key); + + if (pos != mResourceMap->end()) + { + auto existingValue = pos->second.lock(); + + if (existingValue) + return existingValue; + else + mResourceMap->erase(pos); + } + + // Allocate a new instance. + auto newValue = std::make_shared(key, mResourceMap, args...); + + mResourceMap->insert(std::make_pair(key, newValue)); + + return newValue; + } + + + private: + // Keep track of all allocated TData instances. + struct ResourceMap : public std::map> + { + std::mutex mutex; + }; + + std::shared_ptr mResourceMap; + + + // Wrap TData with our own subclass, so we can hook the destructor + // to remove instances from our pool before they are freed. + struct WrappedData : public TData + { + WrappedData(TKey key, std::shared_ptr const& resourceMap, TConstructorArgs... args) + : mKey(key), + mResourceMap(resourceMap), + TData(key, args...) + { } + + ~WrappedData() + { + std::lock_guard lock(mResourceMap->mutex); + + auto pos = mResourceMap->find(mKey); + + // Check for weak reference expiry before erasing, in case DemandCreate runs on + // a different thread at the same time as a previous instance is being destroyed. + // We mustn't erase replacement objects that have just been added! + if (pos != mResourceMap->end() && pos->second.expired()) + { + mResourceMap->erase(pos); + } + } + + TKey mKey; + std::shared_ptr mResourceMap; + }; + }; +} diff --git a/Kits/DirectXTK12/Src/SimpleMath.cpp b/Kits/DirectXTK12/Src/SimpleMath.cpp new file mode 100644 index 00000000..6fee5930 --- /dev/null +++ b/Kits/DirectXTK12/Src/SimpleMath.cpp @@ -0,0 +1,192 @@ +//------------------------------------------------------------------------------------- +// SimpleMath.cpp -- Simplified C++ Math wrapper for DirectXMath +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleMath.h" + +/**************************************************************************** + * + * Constants + * + ****************************************************************************/ + +namespace DirectX +{ + namespace SimpleMath + { + #if defined(_MSC_VER) && (_MSC_VER < 1800) + const Vector2 Vector2::Zero(0.f, 0.f); + const Vector2 Vector2::One(1.f, 1.f); + const Vector2 Vector2::UnitX(1.f, 0.f); + const Vector2 Vector2::UnitY(0.f, 1.f); + + const Vector3 Vector3::Zero(0.f, 0.f, 0.f); + const Vector3 Vector3::One(1.f, 1.f, 1.f); + const Vector3 Vector3::UnitX(1.f, 0.f, 0.f); + const Vector3 Vector3::UnitY(0.f, 1.f, 0.f); + const Vector3 Vector3::UnitZ(0.f, 0.f, 1.f); + const Vector3 Vector3::Up(0.f, 1.f, 0.f); + const Vector3 Vector3::Down(0.f, -1.f, 0.f); + const Vector3 Vector3::Right(1.f, 0.f, 0.f); + const Vector3 Vector3::Left(-1.f, 0.f, 0.f); + const Vector3 Vector3::Forward(0.f, 0.f, -1.f); + const Vector3 Vector3::Backward(0.f, 0.f, 1.f); + + const Vector4 Vector4::Zero(0.f, 0.f, 0.f, 0.f); + const Vector4 Vector4::One(1.f, 1.f, 1.f, 1.f); + const Vector4 Vector4::UnitX(1.f, 0.f, 0.f, 0.f); + const Vector4 Vector4::UnitY(0.f, 1.f, 0.f, 0.f); + const Vector4 Vector4::UnitZ(0.f, 0.f, 1.f, 0.f); + const Vector4 Vector4::UnitW(0.f, 0.f, 0.f, 1.f); + + const Matrix Matrix::Identity(1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f); + + const Quaternion Quaternion::Identity(0.f, 0.f, 0.f, 1.f); + #else + const Vector2 Vector2::Zero = { 0.f, 0.f }; + const Vector2 Vector2::One = { 1.f, 1.f }; + const Vector2 Vector2::UnitX = { 1.f, 0.f }; + const Vector2 Vector2::UnitY = { 0.f, 1.f }; + + const Vector3 Vector3::Zero = { 0.f, 0.f, 0.f }; + const Vector3 Vector3::One = { 1.f, 1.f, 1.f }; + const Vector3 Vector3::UnitX = { 1.f, 0.f, 0.f }; + const Vector3 Vector3::UnitY = { 0.f, 1.f, 0.f }; + const Vector3 Vector3::UnitZ = { 0.f, 0.f, 1.f }; + const Vector3 Vector3::Up = { 0.f, 1.f, 0.f }; + const Vector3 Vector3::Down = { 0.f, -1.f, 0.f }; + const Vector3 Vector3::Right = { 1.f, 0.f, 0.f }; + const Vector3 Vector3::Left = { -1.f, 0.f, 0.f }; + const Vector3 Vector3::Forward = { 0.f, 0.f, -1.f }; + const Vector3 Vector3::Backward = { 0.f, 0.f, 1.f }; + + const Vector4 Vector4::Zero = { 0.f, 0.f, 0.f, 0.f }; + const Vector4 Vector4::One = { 1.f, 1.f, 1.f, 1.f }; + const Vector4 Vector4::UnitX = { 1.f, 0.f, 0.f, 0.f }; + const Vector4 Vector4::UnitY = { 0.f, 1.f, 0.f, 0.f }; + const Vector4 Vector4::UnitZ = { 0.f, 0.f, 1.f, 0.f }; + const Vector4 Vector4::UnitW = { 0.f, 0.f, 0.f, 1.f }; + + const Matrix Matrix::Identity = { 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f }; + + const Quaternion Quaternion::Identity = { 0.f, 0.f, 0.f, 1.f }; + #endif + } +} + + +/**************************************************************************** + * + * Viewport + * + ****************************************************************************/ + +#if defined(__d3d11_h__) || defined(__d3d11_x_h__) +static_assert(sizeof(DirectX::SimpleMath::Viewport) == sizeof(D3D11_VIEWPORT), "Size mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, x) == FIELD_OFFSET(D3D11_VIEWPORT, TopLeftX), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, y) == FIELD_OFFSET(D3D11_VIEWPORT, TopLeftY), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, width) == FIELD_OFFSET(D3D11_VIEWPORT, Width), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, height) == FIELD_OFFSET(D3D11_VIEWPORT, Height), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, minDepth) == FIELD_OFFSET(D3D11_VIEWPORT, MinDepth), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, maxDepth) == FIELD_OFFSET(D3D11_VIEWPORT, MaxDepth), "Layout mismatch"); +#endif + +#if defined(__d3d12_h__) || defined(__d3d12_x_h__) +static_assert(sizeof(DirectX::SimpleMath::Viewport) == sizeof(D3D12_VIEWPORT), "Size mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, x) == FIELD_OFFSET(D3D12_VIEWPORT, TopLeftX), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, y) == FIELD_OFFSET(D3D12_VIEWPORT, TopLeftY), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, width) == FIELD_OFFSET(D3D12_VIEWPORT, Width), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, height) == FIELD_OFFSET(D3D12_VIEWPORT, Height), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, minDepth) == FIELD_OFFSET(D3D12_VIEWPORT, MinDepth), "Layout mismatch"); +static_assert(FIELD_OFFSET(DirectX::SimpleMath::Viewport, maxDepth) == FIELD_OFFSET(D3D12_VIEWPORT, MaxDepth), "Layout mismatch"); +#endif + +RECT DirectX::SimpleMath::Viewport::ComputeDisplayArea(DXGI_SCALING scaling, UINT backBufferWidth, UINT backBufferHeight, int outputWidth, int outputHeight) +{ + RECT rct; + + switch (int(scaling)) + { + case DXGI_SCALING_STRETCH: + // Output fills the entire window area + rct.top = 0; + rct.left = 0; + rct.right = outputWidth; + rct.bottom = outputHeight; + break; + + case 2 /*DXGI_SCALING_ASPECT_RATIO_STRETCH*/: + // Output fills the window area but respects the original aspect ratio, using pillar boxing or letter boxing as required + // Note: This scaling option is not supported for legacy Win32 windows swap chains + { + assert(backBufferHeight > 0); + float aspectRatio = float(backBufferWidth) / float(backBufferHeight); + + // Horizontal fill + float scaledWidth = float(outputWidth); + float scaledHeight = float(outputWidth) / aspectRatio; + if (scaledHeight >= outputHeight) + { + // Do vertical fill + scaledWidth = float(outputHeight) * aspectRatio; + scaledHeight = float(outputHeight); + } + + float offsetX = (float(outputWidth) - scaledWidth) * 0.5f; + float offsetY = (float(outputHeight) - scaledHeight) * 0.5f; + + rct.left = static_cast( offsetX ); + rct.top = static_cast( offsetY ); + rct.right = static_cast( offsetX + scaledWidth ); + rct.bottom = static_cast( offsetY + scaledHeight ); + + // Clip to display window + rct.left = std::max( 0, rct.left ); + rct.top = std::max( 0, rct.top ); + rct.right = std::min( outputWidth, rct.right ); + rct.bottom = std::min( outputHeight, rct.bottom ); + } + break; + + case DXGI_SCALING_NONE: + default: + // Output is displayed in the upper left corner of the window area + rct.top = 0; + rct.left = 0; + rct.right = std::min( backBufferWidth, UINT(outputWidth) ); + rct.bottom = std::min( backBufferHeight, UINT(outputHeight) ); + break; + } + + return rct; +} + +RECT DirectX::SimpleMath::Viewport::ComputeTitleSafeArea(UINT backBufferWidth, UINT backBufferHeight) +{ + float safew = (float(backBufferWidth) + 19.f) / 20.f; + float safeh = (float(backBufferHeight) + 19.f) / 20.f; + + RECT rct; + rct.left = static_cast(safew); + rct.top = static_cast(safeh); + rct.right = static_cast(float(backBufferWidth) - safew + 0.5f); + rct.bottom = static_cast(float(backBufferHeight) - safeh + 0.5f); + + return rct; +} diff --git a/Kits/DirectXTK12/Src/SkinnedEffect.cpp b/Kits/DirectXTK12/Src/SkinnedEffect.cpp new file mode 100644 index 00000000..786da981 --- /dev/null +++ b/Kits/DirectXTK12/Src/SkinnedEffect.cpp @@ -0,0 +1,550 @@ +//-------------------------------------------------------------------------------------- +// File: SkinnedEffect.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "EffectCommon.h" + +using namespace DirectX; + + +// Constant buffer layout. Must match the shader! +struct SkinnedEffectConstants +{ + XMVECTOR diffuseColor; + XMVECTOR emissiveColor; + XMVECTOR specularColorAndPower; + + XMVECTOR lightDirection[IEffectLights::MaxDirectionalLights]; + XMVECTOR lightDiffuseColor[IEffectLights::MaxDirectionalLights]; + XMVECTOR lightSpecularColor[IEffectLights::MaxDirectionalLights]; + + XMVECTOR eyePosition; + + XMVECTOR fogColor; + XMVECTOR fogVector; + + XMMATRIX world; + XMVECTOR worldInverseTranspose[3]; + XMMATRIX worldViewProj; + + XMVECTOR bones[SkinnedEffect::MaxBones][3]; +}; + +static_assert( ( sizeof(SkinnedEffectConstants) % 16 ) == 0, "CB size not padded correctly" ); + + +// Traits type describes our characteristics to the EffectBase template. +struct SkinnedEffectTraits +{ + typedef SkinnedEffectConstants ConstantBufferType; + + static const int VertexShaderCount = 9; + static const int PixelShaderCount = 3; + static const int ShaderPermutationCount = 18; +}; + + +// Internal SkinnedEffect implementation class. +class SkinnedEffect::Impl : public EffectBase +{ +public: + Impl(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription); + + enum DescriptorIndex + { + Texture, + DescriptorCount + }; + + enum RootParameterIndex + { + TextureSRV, + ConstantBuffer, + RootParameterCount + }; + + bool preferPerPixelLighting; + int weightsPerVertex; + + D3D12_GPU_DESCRIPTOR_HANDLE texture; + + EffectLights lights; + + int GetCurrentPipelineStatePermutation() const; + + void Apply(_In_ ID3D12GraphicsCommandList* commandList); +}; + + +// Include the precompiled shader code. +namespace +{ +#if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedVertexLightingOneBone.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedVertexLightingTwoBones.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedVertexLightingFourBones.inc" + + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedOneLightOneBone.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedOneLightTwoBones.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedOneLightFourBones.inc" + + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedPixelLightingOneBone.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedPixelLightingTwoBones.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_VSSkinnedPixelLightingFourBones.inc" + + #include "Shaders/Compiled/XboxOneSkinnedEffect_PSSkinnedVertexLighting.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_PSSkinnedVertexLightingNoFog.inc" + #include "Shaders/Compiled/XboxOneSkinnedEffect_PSSkinnedPixelLighting.inc" +#else + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingOneBone.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingTwoBones.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedVertexLightingFourBones.inc" + + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightOneBone.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightTwoBones.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedOneLightFourBones.inc" + + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingOneBone.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingTwoBones.inc" + #include "Shaders/Compiled/SkinnedEffect_VSSkinnedPixelLightingFourBones.inc" + + #include "Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLighting.inc" + #include "Shaders/Compiled/SkinnedEffect_PSSkinnedVertexLightingNoFog.inc" + #include "Shaders/Compiled/SkinnedEffect_PSSkinnedPixelLighting.inc" +#endif +} + + +const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = +{ + { SkinnedEffect_VSSkinnedVertexLightingOneBone, sizeof(SkinnedEffect_VSSkinnedVertexLightingOneBone) }, + { SkinnedEffect_VSSkinnedVertexLightingTwoBones, sizeof(SkinnedEffect_VSSkinnedVertexLightingTwoBones) }, + { SkinnedEffect_VSSkinnedVertexLightingFourBones, sizeof(SkinnedEffect_VSSkinnedVertexLightingFourBones) }, + + { SkinnedEffect_VSSkinnedOneLightOneBone, sizeof(SkinnedEffect_VSSkinnedOneLightOneBone) }, + { SkinnedEffect_VSSkinnedOneLightTwoBones, sizeof(SkinnedEffect_VSSkinnedOneLightTwoBones) }, + { SkinnedEffect_VSSkinnedOneLightFourBones, sizeof(SkinnedEffect_VSSkinnedOneLightFourBones) }, + + { SkinnedEffect_VSSkinnedPixelLightingOneBone, sizeof(SkinnedEffect_VSSkinnedPixelLightingOneBone) }, + { SkinnedEffect_VSSkinnedPixelLightingTwoBones, sizeof(SkinnedEffect_VSSkinnedPixelLightingTwoBones) }, + { SkinnedEffect_VSSkinnedPixelLightingFourBones, sizeof(SkinnedEffect_VSSkinnedPixelLightingFourBones) }, +}; + + +const int EffectBase::VertexShaderIndices[] = +{ + 0, // vertex lighting, one bone + 0, // vertex lighting, one bone, no fog + 1, // vertex lighting, two bones + 1, // vertex lighting, two bones, no fog + 2, // vertex lighting, four bones + 2, // vertex lighting, four bones, no fog + + 3, // one light, one bone + 3, // one light, one bone, no fog + 4, // one light, two bones + 4, // one light, two bones, no fog + 5, // one light, four bones + 5, // one light, four bones, no fog + + 6, // pixel lighting, one bone + 6, // pixel lighting, one bone, no fog + 7, // pixel lighting, two bones + 7, // pixel lighting, two bones, no fog + 8, // pixel lighting, four bones + 8, // pixel lighting, four bones, no fog +}; + + +const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = +{ + { SkinnedEffect_PSSkinnedVertexLighting, sizeof(SkinnedEffect_PSSkinnedVertexLighting) }, + { SkinnedEffect_PSSkinnedVertexLightingNoFog, sizeof(SkinnedEffect_PSSkinnedVertexLightingNoFog) }, + { SkinnedEffect_PSSkinnedPixelLighting, sizeof(SkinnedEffect_PSSkinnedPixelLighting) }, +}; + + +const int EffectBase::PixelShaderIndices[] = +{ + 0, // vertex lighting, one bone + 1, // vertex lighting, one bone, no fog + 0, // vertex lighting, two bones + 1, // vertex lighting, two bones, no fog + 0, // vertex lighting, four bones + 1, // vertex lighting, four bones, no fog + + 0, // one light, one bone + 1, // one light, one bone, no fog + 0, // one light, two bones + 1, // one light, two bones, no fog + 0, // one light, four bones + 1, // one light, four bones, no fog + + 2, // pixel lighting, one bone + 2, // pixel lighting, one bone, no fog + 2, // pixel lighting, two bones + 2, // pixel lighting, two bones, no fog + 2, // pixel lighting, four bones + 2, // pixel lighting, four bones, no fog +}; + + +// Global pool of per-device SkinnedEffect resources. +SharedResourcePool::DeviceResources> EffectBase::deviceResourcesPool; + + +// Constructor. +SkinnedEffect::Impl::Impl(_In_ ID3D12Device* device, int flags, const EffectPipelineStateDescription& pipelineDescription) + : EffectBase(device), + preferPerPixelLighting(false), + weightsPerVertex(4) +{ + static_assert( _countof(EffectBase::VertexShaderIndices) == SkinnedEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::VertexShaderBytecode) == SkinnedEffectTraits::VertexShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderBytecode) == SkinnedEffectTraits::PixelShaderCount, "array/max mismatch" ); + static_assert( _countof(EffectBase::PixelShaderIndices) == SkinnedEffectTraits::ShaderPermutationCount, "array/max mismatch" ); + + lights.InitializeConstants(constants.specularColorAndPower, constants.lightDirection, constants.lightDiffuseColor, constants.lightSpecularColor); + + for (int i = 0; i < MaxBones; i++) + { + constants.bones[i][0] = g_XMIdentityR0; + constants.bones[i][1] = g_XMIdentityR1; + constants.bones[i][2] = g_XMIdentityR2; + } + + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC sampler(0); + CD3DX12_DESCRIPTOR_RANGE descriptorRanges[DescriptorIndex::DescriptorCount]; + descriptorRanges[DescriptorIndex::Texture].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable( + _countof(descriptorRanges), + descriptorRanges); + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ThrowIfFailed(CreateRootSignature(device, &rsigDesc, mRootSignature.ReleaseAndGetAddressOf())); + + fog.enabled = (flags & EffectFlags::Fog) != 0; + preferPerPixelLighting = (flags & EffectFlags::PerPixelLighting) != 0; + + int sp = GetCurrentPipelineStatePermutation(); + int vi = EffectBase::VertexShaderIndices[sp]; + int pi = EffectBase::PixelShaderIndices[sp]; + + EffectBase::CreatePipelineState( + mRootSignature.Get(), + pipelineDescription.inputLayout, + &EffectBase::VertexShaderBytecode[vi], + &EffectBase::PixelShaderBytecode[pi], + pipelineDescription.blendDesc, + pipelineDescription.depthStencilDesc, + pipelineDescription.rasterizerDesc, + pipelineDescription.renderTargetState, + pipelineDescription.primitiveTopology, + pipelineDescription.stripCutValue); +} + + +int SkinnedEffect::Impl::GetCurrentPipelineStatePermutation() const +{ + int permutation = 0; + + // Use optimized shaders if fog is disabled. + if (!fog.enabled) + { + permutation += 1; + } + + // Evaluate 1, 2, or 4 weights per vertex? + if (weightsPerVertex == 2) + { + permutation += 2; + } + else if (weightsPerVertex == 4) + { + permutation += 4; + } + + if (preferPerPixelLighting) + { + // Do lighting in the pixel shader. + permutation += 12; + } + else if (!lights.lightEnabled[1] && !lights.lightEnabled[2]) + { + // Use the only-bother-with-the-first-light shader optimization. + permutation += 6; + } + + return permutation; +} + + +// Sets our state onto the D3D device. +void SkinnedEffect::Impl::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + // Compute derived parameter values. + matrices.SetConstants(dirtyFlags, constants.worldViewProj); + fog.SetConstants(dirtyFlags, matrices.worldView, constants.fogVector); + lights.SetConstants(dirtyFlags, matrices, constants.world, constants.worldInverseTranspose, constants.eyePosition, constants.diffuseColor, constants.emissiveColor, true); + + UpdateConstants(); + + // Set the root signature + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + + // Set the texture. + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + + // Set constants + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, GetConstantBufferGpuAddress()); + + // Set the pipeline state + commandList->SetPipelineState(EffectBase::mPipelineState.Get()); +} + + +// Public constructor. +SkinnedEffect::SkinnedEffect(_In_ ID3D12Device* device, int effectFlags, const EffectPipelineStateDescription& pipelineDescription) + : pImpl(new Impl(device, effectFlags, pipelineDescription)) +{ +} + + +// Move constructor. +SkinnedEffect::SkinnedEffect(SkinnedEffect&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +SkinnedEffect& SkinnedEffect::operator= (SkinnedEffect&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +SkinnedEffect::~SkinnedEffect() +{ +} + + +void SkinnedEffect::Apply(_In_ ID3D12GraphicsCommandList* commandList) +{ + pImpl->Apply(commandList); +} + +void XM_CALLCONV SkinnedEffect::SetWorld(FXMMATRIX value) +{ + pImpl->matrices.world = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::WorldInverseTranspose | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV SkinnedEffect::SetView(FXMMATRIX value) +{ + pImpl->matrices.view = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj | EffectDirtyFlags::EyePosition | EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV SkinnedEffect::SetProjection(FXMMATRIX value) +{ + pImpl->matrices.projection = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::WorldViewProj; +} + + +void XM_CALLCONV SkinnedEffect::SetDiffuseColor(FXMVECTOR value) +{ + pImpl->lights.diffuseColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV SkinnedEffect::SetEmissiveColor(FXMVECTOR value) +{ + pImpl->lights.emissiveColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void XM_CALLCONV SkinnedEffect::SetSpecularColor(FXMVECTOR value) +{ + // Set xyz to new value, but preserve existing w (specular power). + pImpl->constants.specularColorAndPower = XMVectorSelect(pImpl->constants.specularColorAndPower, value, g_XMSelect1110); + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void SkinnedEffect::SetSpecularPower(float value) +{ + // Set w to new value, but preserve existing xyz (specular color). + pImpl->constants.specularColorAndPower = XMVectorSetW(pImpl->constants.specularColorAndPower, value); + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void SkinnedEffect::DisableSpecular() +{ + // Set specular color to black, power to 1 + // Note: Don't use a power of 0 or the shader will generate strange highlights on non-specular materials + + pImpl->constants.specularColorAndPower = g_XMIdentityR3; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + +void SkinnedEffect::SetAlpha(float value) +{ + pImpl->lights.alpha = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + +void XM_CALLCONV SkinnedEffect::SetAmbientLightColor(FXMVECTOR value) +{ + pImpl->lights.ambientLightColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::MaterialColor; +} + + +void SkinnedEffect::SetLightEnabled(int whichLight, bool value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightEnabled(whichLight, value, pImpl->constants.lightDiffuseColor, pImpl->constants.lightSpecularColor); +} + + +void XM_CALLCONV SkinnedEffect::SetLightDirection(int whichLight, FXMVECTOR value) +{ + EffectLights::ValidateLightIndex(whichLight); + + pImpl->constants.lightDirection[whichLight] = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void XM_CALLCONV SkinnedEffect::SetLightDiffuseColor(int whichLight, FXMVECTOR value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightDiffuseColor(whichLight, value, pImpl->constants.lightDiffuseColor); +} + + +void XM_CALLCONV SkinnedEffect::SetLightSpecularColor(int whichLight, FXMVECTOR value) +{ + pImpl->dirtyFlags |= pImpl->lights.SetLightSpecularColor(whichLight, value, pImpl->constants.lightSpecularColor); +} + + +void SkinnedEffect::EnableDefaultLighting() +{ + EffectLights::EnableDefaultLighting(this); +} + +void SkinnedEffect::SetFogStart(float value) +{ + pImpl->fog.start = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void SkinnedEffect::SetFogEnd(float value) +{ + pImpl->fog.end = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::FogVector; +} + + +void XM_CALLCONV SkinnedEffect::SetFogColor(FXMVECTOR value) +{ + pImpl->constants.fogColor = value; + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void SkinnedEffect::SetTexture(_In_ D3D12_GPU_DESCRIPTOR_HANDLE srvDescriptor) +{ + pImpl->texture = srvDescriptor; +} + + +void SkinnedEffect::SetWeightsPerVertex(int value) +{ + if ((value != 1) && + (value != 2) && + (value != 4)) + { + throw std::out_of_range("WeightsPerVertex must be 1, 2, or 4"); + } + + pImpl->weightsPerVertex = value; +} + + +void SkinnedEffect::SetBoneTransforms(_In_reads_(count) XMMATRIX const* value, size_t count) +{ + if (count > MaxBones) + throw std::out_of_range("count parameter out of range"); + + auto boneConstant = pImpl->constants.bones; + + for (size_t i = 0; i < count; i++) + { + XMMATRIX boneMatrix = XMMatrixTranspose(value[i]); + + boneConstant[i][0] = boneMatrix.r[0]; + boneConstant[i][1] = boneMatrix.r[1]; + boneConstant[i][2] = boneMatrix.r[2]; + } + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} + + +void SkinnedEffect::ResetBoneTransforms() +{ + auto boneConstant = pImpl->constants.bones; + + XMMATRIX id = XMMatrixIdentity(); + + for(size_t i = 0; i < MaxBones; ++i) + { + boneConstant[i][0] = g_XMIdentityR0; + boneConstant[i][1] = g_XMIdentityR1; + boneConstant[i][2] = g_XMIdentityR2; + } + + pImpl->dirtyFlags |= EffectDirtyFlags::ConstantBuffer; +} diff --git a/Kits/DirectXTK12/Src/SpriteBatch.cpp b/Kits/DirectXTK12/Src/SpriteBatch.cpp new file mode 100644 index 00000000..df732400 --- /dev/null +++ b/Kits/DirectXTK12/Src/SpriteBatch.cpp @@ -0,0 +1,1078 @@ +//-------------------------------------------------------------------------------------- +// File: SpriteBatch.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include "SpriteBatch.h" +#include "CommonStates.h" +#include "VertexTypes.h" +#include "SharedResourcePool.h" +#include "AlignedNew.h" +#include "ResourceUploadBatch.h" +#include "GraphicsMemory.h" +#include "DirectXHelpers.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + // Include the precompiled shader code. + #if defined(_XBOX_ONE) && defined(_TITLE) + #include "Shaders/Compiled/XboxOneSpriteEffect_SpriteVertexShader.inc" + #include "Shaders/Compiled/XboxOneSpriteEffect_SpritePixelShader.inc" + #else + #include "Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc" + #include "Shaders/Compiled/SpriteEffect_SpritePixelShader.inc" + #endif + + inline bool operator ! (D3D12_GPU_DESCRIPTOR_HANDLE h) + { + return h.ptr == 0; + } + inline bool operator != (D3D12_GPU_DESCRIPTOR_HANDLE a, D3D12_GPU_DESCRIPTOR_HANDLE b) + { + return a.ptr != b.ptr; + } + inline bool operator < (D3D12_GPU_DESCRIPTOR_HANDLE a, D3D12_GPU_DESCRIPTOR_HANDLE b) + { + return a.ptr < b.ptr; + } + + // Helper converts a RECT to XMVECTOR. + inline XMVECTOR LoadRect(_In_ RECT const* rect) + { + XMVECTOR v = XMLoadInt4(reinterpret_cast(rect)); + + v = XMConvertVectorIntToFloat(v, 0); + + // Convert right/bottom to width/height. + v -= XMVectorPermute<0, 1, 4, 5>(XMVectorZero(), v); + + return v; + } +} + +// Internal SpriteBatch implementation class. +__declspec(align(16)) class SpriteBatch::Impl : public AlignedNew +{ +public: + Impl(_In_ ID3D12Device* device, + _In_ ResourceUploadBatch& upload, + _In_ const SpriteBatchPipelineStateDescription* psoDesc, + _In_opt_ const D3D12_VIEWPORT* viewport); + + void XM_CALLCONV Begin( + _In_ ID3D12GraphicsCommandList* commandList, + _In_opt_ SpriteSortMode sortMode = SpriteSortMode_Deferred, + _In_opt_ FXMMATRIX transformMatrix = MatrixIdentity); + void End(); + + void XM_CALLCONV Draw(_In_ D3D12_GPU_DESCRIPTOR_HANDLE texture, + _In_ XMUINT2 textureSize, + FXMVECTOR destination, + _In_opt_ RECT const* sourceRectangle, + FXMVECTOR color, + FXMVECTOR originRotationDepth, + int flags); + + // Info about a single sprite that is waiting to be drawn. + __declspec(align(16)) struct SpriteInfo : public AlignedNew + { + XMFLOAT4A source; + XMFLOAT4A destination; + XMFLOAT4A color; + XMFLOAT4A originRotationDepth; + D3D12_GPU_DESCRIPTOR_HANDLE texture; + XMVECTOR textureSize; + int flags; + + // Combine values from the public SpriteEffects enum with these internal-only flags. + static const int SourceInTexels = 4; + static const int DestSizeInPixels = 8; + + static_assert((SpriteEffects_FlipBoth & (SourceInTexels | DestSizeInPixels)) == 0, "Flag bits must not overlap"); + }; + + DXGI_MODE_ROTATION mRotation; + + bool mSetViewport; + D3D12_VIEWPORT mViewPort; + +private: + // Implementation helper methods. + void GrowSpriteQueue(); + void PrepareForRendering(); + void FlushBatch(); + void SortSprites(); + void GrowSortedSprites(); + + void RenderBatch(_In_ D3D12_GPU_DESCRIPTOR_HANDLE texture, _In_ XMVECTOR textureSize, _In_reads_(count) SpriteInfo const* const* sprites, size_t count); + + static void XM_CALLCONV RenderSprite(_In_ SpriteInfo const* sprite, + _Out_writes_(VerticesPerSprite) VertexPositionColorTexture* vertices, + FXMVECTOR textureSize, + FXMVECTOR inverseTextureSize); + + XMMATRIX GetViewportTransform(_In_ DXGI_MODE_ROTATION rotation); + + // Constants. + static const size_t MaxBatchSize = 2048; + static const size_t MinBatchSize = 128; + static const size_t InitialQueueSize = 64; + static const size_t VerticesPerSprite = 4; + static const size_t IndicesPerSprite = 6; + + // + // The following functions and members are used to create the default pipeline state objects. + // + static const D3D12_SHADER_BYTECODE s_DefaultVertexShaderByteCode; + static const D3D12_SHADER_BYTECODE s_DefaultPixelShaderByteCode; + static const D3D12_INPUT_LAYOUT_DESC s_DefaultInputLayoutDesc; + static const D3D12_BLEND_DESC s_DefaultBlendDesc; + static const D3D12_RASTERIZER_DESC s_DefaultRasterizerDesc; + static const D3D12_DEPTH_STENCIL_DESC s_DefaultDepthStencilDesc; + + + // Queue of sprites waiting to be drawn. + std::unique_ptr mSpriteQueue; + + size_t mSpriteQueueCount; + size_t mSpriteQueueArraySize; + + + // To avoid needlessly copying around bulky SpriteInfo structures, we leave that + // actual data alone and just sort this array of pointers instead. But we want contiguous + // memory for cache efficiency, so these pointers are just shortcuts into the single + // mSpriteQueue array, and we take care to keep them in order when sorting is disabled. + std::vector mSortedSprites; + + + // Mode settings from the last Begin call. + bool mInBeginEndPair; + + SpriteSortMode mSortMode; + ComPtr mPSO; + ComPtr mRootSignature; + XMMATRIX mTransformMatrix; + ComPtr mCommandList; + + // Batched data + GraphicsResource mVertexSegment; + size_t mVertexPageSize; + size_t mSpriteCount; + GraphicsResource mConstantBuffer; + + enum DescriptorIndex + { + Texture, + DescriptorCount + }; + + enum RootParameterIndex + { + TextureSRV, + ConstantBuffer, + RootParameterCount + }; + + // Only one of these helpers is allocated per D3D device, even if there are multiple SpriteBatch instances. + struct DeviceResources + { + DeviceResources(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload); + + ComPtr indexBuffer; + D3D12_INDEX_BUFFER_VIEW indexBufferView; + ComPtr rootSignature; + + private: + void CreateIndexBuffer(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload); + void CreateRootSignature(_In_ ID3D12Device* device); + + static std::vector CreateIndexValues(); + }; + + // Per-device data. + std::shared_ptr mDeviceResources; + static SharedResourcePool deviceResourcesPool; +}; + + +// Global pools of per-device and per-context SpriteBatch resources. +SharedResourcePool SpriteBatch::Impl::deviceResourcesPool; + + +// Constants. +const XMMATRIX SpriteBatch::MatrixIdentity = XMMatrixIdentity(); +const XMFLOAT2 SpriteBatch::Float2Zero(0, 0); + +const D3D12_SHADER_BYTECODE SpriteBatch::Impl::s_DefaultVertexShaderByteCode = {SpriteEffect_SpriteVertexShader, sizeof(SpriteEffect_SpriteVertexShader)}; +const D3D12_SHADER_BYTECODE SpriteBatch::Impl::s_DefaultPixelShaderByteCode = {SpriteEffect_SpritePixelShader, sizeof(SpriteEffect_SpritePixelShader)}; +const D3D12_INPUT_LAYOUT_DESC SpriteBatch::Impl::s_DefaultInputLayoutDesc = VertexPositionColorTexture::InputLayout; +const D3D12_BLEND_DESC SpriteBatch::Impl::s_DefaultBlendDesc = {FALSE, FALSE, {TRUE, FALSE, D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_LOGIC_OP_CLEAR, D3D12_COLOR_WRITE_ENABLE_ALL}}; +const D3D12_RASTERIZER_DESC SpriteBatch::Impl::s_DefaultRasterizerDesc = {D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, FALSE, 0, 0, 0, FALSE, FALSE, FALSE, 0, D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF}; +const D3D12_DEPTH_STENCIL_DESC SpriteBatch::Impl::s_DefaultDepthStencilDesc = {FALSE, D3D12_DEPTH_WRITE_MASK_ALL, D3D12_COMPARISON_FUNC_ALWAYS, FALSE, 0, 0}; + +// Per-device constructor. +SpriteBatch::Impl::DeviceResources::DeviceResources(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload) +{ + CreateIndexBuffer(device, upload); + CreateRootSignature(device); +} + +// Creates the SpriteBatch index buffer. +void SpriteBatch::Impl::DeviceResources::CreateIndexBuffer(_In_ ID3D12Device* device, _In_ ResourceUploadBatch& upload) +{ + static_assert((MaxBatchSize * VerticesPerSprite) < USHRT_MAX, "MaxBatchSize too large for 16-bit indices"); + + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(short) * MaxBatchSize * IndicesPerSprite); + + // Create the constant buffer. + ThrowIfFailed(device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(indexBuffer.ReleaseAndGetAddressOf()))); + + auto indexValues = CreateIndexValues(); + + D3D12_SUBRESOURCE_DATA indexDataDesc = {}; + indexDataDesc.pData = indexValues.data(); + indexDataDesc.RowPitch = (LONG_PTR) bufferDesc.Width; + indexDataDesc.SlicePitch = indexDataDesc.RowPitch; + + // Upload the resource + upload.Upload(indexBuffer.Get(), 0, &indexDataDesc, 1); + upload.Transition(indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER); + SetDebugObjectName(indexBuffer.Get(), L"DirectXTK:SpriteBatch Index Buffer"); + + // Create the index buffer view + indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); + indexBufferView.Format = DXGI_FORMAT_R16_UINT; + indexBufferView.SizeInBytes = (UINT) bufferDesc.Width; +} + +void SpriteBatch::Impl::DeviceResources::CreateRootSignature(_In_ ID3D12Device* device) +{ + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS; + + CD3DX12_STATIC_SAMPLER_DESC sampler(0); + CD3DX12_DESCRIPTOR_RANGE descriptorRanges[DescriptorIndex::DescriptorCount]; + descriptorRanges[DescriptorIndex::Texture].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount]; + rootParameters[RootParameterIndex::TextureSRV].InitAsDescriptorTable( + _countof(descriptorRanges), + descriptorRanges); + rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL); + CD3DX12_ROOT_SIGNATURE_DESC rsigDesc; + rsigDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, rootSignatureFlags); + + ThrowIfFailed(::CreateRootSignature(device, &rsigDesc, rootSignature.ReleaseAndGetAddressOf())); +} + +// Helper for populating the SpriteBatch index buffer. +std::vector SpriteBatch::Impl::DeviceResources::CreateIndexValues() +{ + std::vector indices; + + indices.reserve(MaxBatchSize * IndicesPerSprite); + + for (short i = 0; i < MaxBatchSize * VerticesPerSprite; i += VerticesPerSprite) + { + indices.push_back(i); + indices.push_back(i + 1); + indices.push_back(i + 2); + + indices.push_back(i + 1); + indices.push_back(i + 3); + indices.push_back(i + 2); + } + + return indices; +} + +// Per-SpriteBatch constructor. +_Use_decl_annotations_ +SpriteBatch::Impl::Impl(ID3D12Device* device, ResourceUploadBatch& upload, const SpriteBatchPipelineStateDescription* psoDesc, const D3D12_VIEWPORT* viewport) + : mRotation(DXGI_MODE_ROTATION_IDENTITY), + mSetViewport(false), + mSpriteQueueCount(0), + mSpriteQueueArraySize(0), + mInBeginEndPair(false), + mSortMode(SpriteSortMode_Deferred), + mTransformMatrix(MatrixIdentity), + mDeviceResources(deviceResourcesPool.DemandCreate(device, upload)), + mVertexPageSize(sizeof(VertexPositionNormalColorTexture) * MaxBatchSize * VerticesPerSprite), + mVertexSegment {}, + mSpriteCount(0) +{ + if (psoDesc == nullptr) + throw std::exception("SpriteBatch: PSO description cannot be null."); + + if (psoDesc->renderTargetState == nullptr) + throw std::exception("SpriteBatchPipelineStateDescription must have a non-null render target state."); + + if (viewport != nullptr) + { + mViewPort = *viewport; + mSetViewport = true; + } + + mRootSignature = mDeviceResources->rootSignature.Get(); + D3D12_SHADER_BYTECODE vertexShader = s_DefaultVertexShaderByteCode; + D3D12_SHADER_BYTECODE pixelShader = s_DefaultPixelShaderByteCode; + + if (psoDesc->shaders) + { + if (psoDesc->shaders->rootSignature) + mRootSignature = psoDesc->shaders->rootSignature; + if (psoDesc->shaders->vertexShaderByteCode) + vertexShader = *psoDesc->shaders->vertexShaderByteCode; + if (psoDesc->shaders->pixelShaderByteCode) + pixelShader = *psoDesc->shaders->pixelShaderByteCode; + } + + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3dDesc = {}; + d3dDesc.pRootSignature = mRootSignature.Get(); + d3dDesc.VS = vertexShader; + d3dDesc.PS = pixelShader; + d3dDesc.InputLayout = s_DefaultInputLayoutDesc; + d3dDesc.BlendState = psoDesc->blendDesc ? *psoDesc->blendDesc : s_DefaultBlendDesc; + d3dDesc.DepthStencilState = psoDesc->depthStencilDesc ? *psoDesc->depthStencilDesc : s_DefaultDepthStencilDesc; + d3dDesc.RasterizerState = psoDesc->rasterizerDesc ? *psoDesc->rasterizerDesc : s_DefaultRasterizerDesc; + d3dDesc.DSVFormat = psoDesc->renderTargetState->dsvFormat; + d3dDesc.NodeMask = psoDesc->renderTargetState->nodeMask; + d3dDesc.NumRenderTargets = psoDesc->renderTargetState->numRenderTargets; + memcpy(d3dDesc.RTVFormats, psoDesc->renderTargetState->rtvFormats, sizeof(d3dDesc.RTVFormats)); + d3dDesc.SampleDesc = psoDesc->renderTargetState->sampleDesc; + d3dDesc.SampleMask = psoDesc->renderTargetState->sampleMask; + d3dDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + d3dDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + + ThrowIfFailed(device->CreateGraphicsPipelineState( + &d3dDesc, + IID_GRAPHICS_PPV_ARGS(mPSO.ReleaseAndGetAddressOf()))); +} + +// Begins a batch of sprite drawing operations. +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Impl::Begin(ID3D12GraphicsCommandList* commandList, SpriteSortMode sortMode, FXMMATRIX transformMatrix) +{ + if (mInBeginEndPair) + throw std::exception("Cannot nest Begin calls on a single SpriteBatch"); + + mSortMode = sortMode; + mTransformMatrix = transformMatrix; + mCommandList = commandList; + mSpriteCount = 0; + + if (sortMode == SpriteSortMode_Immediate) + { + PrepareForRendering(); + } + + mInBeginEndPair = true; +} + + +// Ends a batch of sprite drawing operations. +void SpriteBatch::Impl::End() +{ + if (!mInBeginEndPair) + throw std::exception("Begin must be called before End"); + + if (mSortMode != SpriteSortMode_Immediate) + { + PrepareForRendering(); + FlushBatch(); + } + + // Release this memory + mVertexSegment.Reset(); + + // Break circular reference chains, in case the state lambda closed + // over an object that holds a reference to this SpriteBatch. + mCommandList = nullptr; + mInBeginEndPair = false; +} + + +// Adds a single sprite to the queue. +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Impl::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + FXMVECTOR destination, + RECT const* sourceRectangle, + FXMVECTOR color, + FXMVECTOR originRotationDepth, + int flags) +{ + if (!mInBeginEndPair) + throw std::exception("Begin must be called before Draw"); + + // Get a pointer to the output sprite. + if (mSpriteQueueCount >= mSpriteQueueArraySize) + { + GrowSpriteQueue(); + } + + SpriteInfo* sprite = &mSpriteQueue[mSpriteQueueCount]; + + XMVECTOR dest = destination; + + if (sourceRectangle) + { + // User specified an explicit source region. + XMVECTOR source = LoadRect(sourceRectangle); + + XMStoreFloat4A(&sprite->source, source); + + // If the destination size is relative to the source region, convert it to pixels. + if (!(flags & SpriteInfo::DestSizeInPixels)) + { + dest = XMVectorPermute<0, 1, 6, 7>(dest, dest * source); // dest.zw *= source.zw + } + + flags |= SpriteInfo::SourceInTexels | SpriteInfo::DestSizeInPixels; + } + else + { + // No explicit source region, so use the entire texture. + static const XMVECTORF32 wholeTexture = {0, 0, 1, 1}; + + XMStoreFloat4A(&sprite->source, wholeTexture); + } + + // Convert texture size + XMVECTOR textureSizeV = XMLoadUInt2(&textureSize); + + // Store sprite parameters. + XMStoreFloat4A(&sprite->destination, dest); + XMStoreFloat4A(&sprite->color, color); + XMStoreFloat4A(&sprite->originRotationDepth, originRotationDepth); + + sprite->texture = texture; + sprite->textureSize = textureSizeV; + sprite->flags = flags; + + if (mSortMode == SpriteSortMode_Immediate) + { + // If we are in immediate mode, draw this sprite straight away. + RenderBatch(texture, textureSizeV, &sprite, 1); + } + else + { + // Queue this sprite for later sorting and batched rendering. + mSpriteQueueCount++; + } +} + + +// Dynamically expands the array used to store pending sprite information. +void SpriteBatch::Impl::GrowSpriteQueue() +{ + // Grow by a factor of 2. + size_t newSize = std::max(InitialQueueSize, mSpriteQueueArraySize * 2); + + // Allocate the new array. + std::unique_ptr newArray(new SpriteInfo[newSize]); + + // Copy over any existing sprites. + for (size_t i = 0; i < mSpriteQueueCount; i++) + { + newArray[i] = mSpriteQueue[i]; + } + + // Replace the previous array with the new one. + mSpriteQueue = std::move(newArray); + mSpriteQueueArraySize = newSize; + + // Clear any dangling SpriteInfo pointers left over from previous rendering. + mSortedSprites.clear(); +} + + +// Sets up D3D device state ready for drawing sprites. +void SpriteBatch::Impl::PrepareForRendering() +{ + auto commandList = mCommandList.Get(); + + // Set root signature + commandList->SetGraphicsRootSignature(mRootSignature.Get()); + + // Set render state + commandList->SetPipelineState(mPSO.Get()); + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Set the index buffer. + commandList->IASetIndexBuffer(&mDeviceResources->indexBufferView); + + // Set the transform matrix. + XMMATRIX transformMatrix = (mRotation == DXGI_MODE_ROTATION_UNSPECIFIED) + ? mTransformMatrix + : (mTransformMatrix * GetViewportTransform(mRotation)); + + mConstantBuffer = GraphicsMemory::Get().AllocateConstant(transformMatrix); + commandList->SetGraphicsRootConstantBufferView(RootParameterIndex::ConstantBuffer, mConstantBuffer.GpuAddress()); +} + + +// Sends queued sprites to the graphics device. +void SpriteBatch::Impl::FlushBatch() +{ + if (!mSpriteQueueCount) + return; + + SortSprites(); + + // Walk through the sorted sprite list, looking for adjacent entries that share a texture. + D3D12_GPU_DESCRIPTOR_HANDLE batchTexture = {}; + XMVECTOR batchTextureSize = {}; + size_t batchStart = 0; + + for (size_t pos = 0; pos < mSpriteQueueCount; pos++) + { + D3D12_GPU_DESCRIPTOR_HANDLE texture = mSortedSprites[pos]->texture; + XMVECTOR textureSize = mSortedSprites[pos]->textureSize; + + // Flush whenever the texture changes. + if (texture != batchTexture) + { + if (pos > batchStart) + { + RenderBatch(batchTexture, batchTextureSize, &mSortedSprites[batchStart], pos - batchStart); + } + + batchTexture = texture; + batchTextureSize = textureSize; + batchStart = pos; + } + } + + // Flush the final batch. + RenderBatch(batchTexture, batchTextureSize, &mSortedSprites[batchStart], mSpriteQueueCount - batchStart); + + // Reset the queue. + mSpriteQueueCount = 0; + + // When sorting is disabled, we persist mSortedSprites data from one batch to the next, to avoid + // uneccessary work in GrowSortedSprites. But we never reuse these when sorting, because re-sorting + // previously sorted items gives unstable ordering if some sprites have identical sort keys. + if (mSortMode != SpriteSortMode_Deferred) + { + mSortedSprites.clear(); + } +} + + +// Sorts the array of queued sprites. +void SpriteBatch::Impl::SortSprites() +{ + // Fill the mSortedSprites vector. + if (mSortedSprites.size() < mSpriteQueueCount) + { + GrowSortedSprites(); + } + + switch (mSortMode) + { + case SpriteSortMode_Texture: + // Sort by texture. + std::sort(mSortedSprites.begin(), mSortedSprites.begin() + mSpriteQueueCount, [] (SpriteInfo const* x, SpriteInfo const* y) -> bool + { + return x->texture < y->texture; + }); + break; + + case SpriteSortMode_BackToFront: + // Sort back to front. + std::sort(mSortedSprites.begin(), mSortedSprites.begin() + mSpriteQueueCount, [] (SpriteInfo const* x, SpriteInfo const* y) -> bool + { + return x->originRotationDepth.w > y->originRotationDepth.w; + }); + break; + + case SpriteSortMode_FrontToBack: + // Sort front to back. + std::sort(mSortedSprites.begin(), mSortedSprites.begin() + mSpriteQueueCount, [] (SpriteInfo const* x, SpriteInfo const* y) -> bool + { + return x->originRotationDepth.w < y->originRotationDepth.w; + }); + break; + } +} + + +// Populates the mSortedSprites vector with pointers to individual elements of the mSpriteQueue array. +void SpriteBatch::Impl::GrowSortedSprites() +{ + size_t previousSize = mSortedSprites.size(); + + mSortedSprites.resize(mSpriteQueueCount); + + for (size_t i = previousSize; i < mSpriteQueueCount; i++) + { + mSortedSprites[i] = &mSpriteQueue[i]; + } +} + + +// Submits a batch of sprites to the GPU. +_Use_decl_annotations_ +void SpriteBatch::Impl::RenderBatch(D3D12_GPU_DESCRIPTOR_HANDLE texture, XMVECTOR textureSize, SpriteInfo const* const* sprites, size_t count) +{ + auto commandList = mCommandList.Get(); + + // Draw using the specified texture. + commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRV, texture); + + // Convert to vector format. + XMVECTOR inverseTextureSize = XMVectorReciprocal(textureSize); + + while (count > 0) + { + // How many sprites do we want to draw? + size_t batchSize = count; + + // How many sprites does the D3D vertex buffer have room for? + size_t remainingSpace = MaxBatchSize - mSpriteCount; + + if (batchSize > remainingSpace) + { + if (remainingSpace < MinBatchSize) + { + // If we are out of room, or about to submit an excessively small batch, wrap back to the start of the vertex buffer. + mSpriteCount = 0; + + batchSize = std::min(count, MaxBatchSize); + } + else + { + // Take however many sprites fit in what's left of the vertex buffer. + batchSize = remainingSpace; + } + } + + // Allocate a new page of vertex memory if we're starting the batch + if (mSpriteCount == 0) + { + mVertexSegment = GraphicsMemory::Get().Allocate(mVertexPageSize); + } + + auto vertices = static_cast(mVertexSegment.Memory()) + mSpriteCount * VerticesPerSprite; + + // Generate sprite vertex data. + for (size_t i = 0; i < batchSize; i++) + { + assert(i < count); + _Analysis_assume_(i < count); + RenderSprite(sprites[i], vertices, textureSize, inverseTextureSize); + + vertices += VerticesPerSprite; + } + + // Set the vertex buffer view + D3D12_VERTEX_BUFFER_VIEW vbv; + size_t spriteVertexTotalSize = sizeof(VertexPositionColorTexture) * VerticesPerSprite; + vbv.BufferLocation = mVertexSegment.GpuAddress() + mSpriteCount * spriteVertexTotalSize; + vbv.StrideInBytes = sizeof(VertexPositionColorTexture); + vbv.SizeInBytes = (UINT) (batchSize * spriteVertexTotalSize); + commandList->IASetVertexBuffers(0, 1, &vbv); + + // Ok lads, the time has come for us draw ourselves some sprites! + UINT indexCount = (UINT) batchSize * IndicesPerSprite; + + commandList->DrawIndexedInstanced(indexCount, 1, 0, 0, 0); + + // Advance the buffer position. + mSpriteCount += batchSize; + + sprites += batchSize; + count -= batchSize; + } +} + + +// Generates vertex data for drawing a single sprite. +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Impl::RenderSprite(SpriteInfo const* sprite, VertexPositionColorTexture* vertices, FXMVECTOR textureSize, FXMVECTOR inverseTextureSize) +{ + // Load sprite parameters into SIMD registers. + XMVECTOR source = XMLoadFloat4A(&sprite->source); + XMVECTOR destination = XMLoadFloat4A(&sprite->destination); + XMVECTOR color = XMLoadFloat4A(&sprite->color); + XMVECTOR originRotationDepth = XMLoadFloat4A(&sprite->originRotationDepth); + + float rotation = sprite->originRotationDepth.z; + int flags = sprite->flags; + + // Extract the source and destination sizes into separate vectors. + XMVECTOR sourceSize = XMVectorSwizzle<2, 3, 2, 3>(source); + XMVECTOR destinationSize = XMVectorSwizzle<2, 3, 2, 3>(destination); + + // Scale the origin offset by source size, taking care to avoid overflow if the source region is zero. + XMVECTOR isZeroMask = XMVectorEqual(sourceSize, XMVectorZero()); + XMVECTOR nonZeroSourceSize = XMVectorSelect(sourceSize, g_XMEpsilon, isZeroMask); + + XMVECTOR origin = XMVectorDivide(originRotationDepth, nonZeroSourceSize); + + // Convert the source region from texels to mod-1 texture coordinate format. + if (flags & SpriteInfo::SourceInTexels) + { + source *= inverseTextureSize; + sourceSize *= inverseTextureSize; + } + else + { + origin *= inverseTextureSize; + } + + // If the destination size is relative to the source region, convert it to pixels. + if (!(flags & SpriteInfo::DestSizeInPixels)) + { + destinationSize *= textureSize; + } + + // Compute a 2x2 rotation matrix. + XMVECTOR rotationMatrix1; + XMVECTOR rotationMatrix2; + + if (rotation != 0) + { + float sin, cos; + + XMScalarSinCos(&sin, &cos, rotation); + + XMVECTOR sinV = XMLoadFloat(&sin); + XMVECTOR cosV = XMLoadFloat(&cos); + + rotationMatrix1 = XMVectorMergeXY(cosV, sinV); + rotationMatrix2 = XMVectorMergeXY(-sinV, cosV); + } + else + { + rotationMatrix1 = g_XMIdentityR0; + rotationMatrix2 = g_XMIdentityR1; + } + + // The four corner vertices are computed by transforming these unit-square positions. + static XMVECTORF32 cornerOffsets[VerticesPerSprite] = + { + { 0, 0 }, + { 1, 0 }, + { 0, 1 }, + { 1, 1 }, + }; + + // Tricksy alert! Texture coordinates are computed from the same cornerOffsets + // table as vertex positions, but if the sprite is mirrored, this table + // must be indexed in a different order. This is done as follows: + // + // position = cornerOffsets[i] + // texcoord = cornerOffsets[i ^ SpriteEffects] + + static_assert(SpriteEffects_FlipHorizontally == 1 && + SpriteEffects_FlipVertically == 2, "If you change these enum values, the mirroring implementation must be updated to match"); + + int mirrorBits = flags & 3; + + // Generate the four output vertices. + for (int i = 0; i < VerticesPerSprite; i++) + { + // Calculate position. + XMVECTOR cornerOffset = (cornerOffsets[i] - origin) * destinationSize; + + // Apply 2x2 rotation matrix. + XMVECTOR position1 = XMVectorMultiplyAdd(XMVectorSplatX(cornerOffset), rotationMatrix1, destination); + XMVECTOR position2 = XMVectorMultiplyAdd(XMVectorSplatY(cornerOffset), rotationMatrix2, position1); + + // Set z = depth. + XMVECTOR position = XMVectorPermute<0, 1, 7, 6>(position2, originRotationDepth); + + // Write position as a Float4, even though VertexPositionColor::position is an XMFLOAT3. + // This is faster, and harmless as we are just clobbering the first element of the + // following color field, which will immediately be overwritten with its correct value. + XMStoreFloat4(reinterpret_cast(&vertices[i].position), position); + + // Write the color. + XMStoreFloat4(&vertices[i].color, color); + + // Compute and write the texture coordinate. + XMVECTOR textureCoordinate = XMVectorMultiplyAdd(cornerOffsets[i ^ mirrorBits], sourceSize, source); + + XMStoreFloat2(&vertices[i].textureCoordinate, textureCoordinate); + } +} + + +// Generates a viewport transform matrix for rendering sprites using x-right y-down screen pixel coordinates. +XMMATRIX SpriteBatch::Impl::GetViewportTransform(_In_ DXGI_MODE_ROTATION rotation) +{ + if (!mSetViewport) + throw std::exception("Viewport not set."); + + // Compute the matrix. + float xScale = (mViewPort.Width > 0) ? 2.0f / mViewPort.Width : 0.0f; + float yScale = (mViewPort.Height > 0) ? 2.0f / mViewPort.Height : 0.0f; + + switch (rotation) + { + case DXGI_MODE_ROTATION_ROTATE90: + return XMMATRIX + ( + 0, -yScale, 0, 0, + -xScale, 0, 0, 0, + 0, 0, 1, 0, + 1, 1, 0, 1 + ); + + case DXGI_MODE_ROTATION_ROTATE270: + return XMMATRIX + ( + 0, yScale, 0, 0, + xScale, 0, 0, 0, + 0, 0, 1, 0, + -1, -1, 0, 1 + ); + + case DXGI_MODE_ROTATION_ROTATE180: + return XMMATRIX + ( + -xScale, 0, 0, 0, + 0, yScale, 0, 0, + 0, 0, 1, 0, + 1, -1, 0, 1 + ); + + default: + return XMMATRIX + ( + xScale, 0, 0, 0, + 0, -yScale, 0, 0, + 0, 0, 1, 0, + -1, 1, 0, 1 + ); + } +} + + +// Public constructor. +_Use_decl_annotations_ +SpriteBatch::SpriteBatch(ID3D12Device* device, + ResourceUploadBatch& upload, + const SpriteBatchPipelineStateDescription* psoDesc, + const D3D12_VIEWPORT* viewport) + : pImpl(new Impl(device, upload, psoDesc, viewport)) +{ +} + + +// Move constructor. +SpriteBatch::SpriteBatch(SpriteBatch&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +SpriteBatch& SpriteBatch::operator= (SpriteBatch&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +SpriteBatch::~SpriteBatch() +{ +} + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Begin( + ID3D12GraphicsCommandList* commandList, + SpriteSortMode sortMode, + FXMMATRIX transformMatrix) +{ + pImpl->Begin( + commandList, + sortMode, + transformMatrix); +} + + +void SpriteBatch::End() +{ + pImpl->End(); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + XMFLOAT2 const& position, + FXMVECTOR color) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 5>(XMLoadFloat2(&position), g_XMOne); // x, y, 1, 1 + + pImpl->Draw(texture, textureSize, destination, nullptr, color, g_XMZero, 0); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + XMFLOAT2 const& position, + RECT const* sourceRectangle, + FXMVECTOR color, + float rotation, + XMFLOAT2 const& origin, + float scale, + SpriteEffects effects, + float layerDepth) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 4>(XMLoadFloat2(&position), XMLoadFloat(&scale)); // x, y, scale, scale + + XMVECTOR originRotationDepth = XMVectorSet(origin.x, origin.y, rotation, layerDepth); + + pImpl->Draw(texture, textureSize, destination, sourceRectangle, color, originRotationDepth, effects); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + XMFLOAT2 const& position, + RECT const* sourceRectangle, + FXMVECTOR color, + float rotation, + XMFLOAT2 const& origin, + XMFLOAT2 const& scale, + SpriteEffects effects, + float layerDepth) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 5>(XMLoadFloat2(&position), XMLoadFloat2(&scale)); // x, y, scale.x, scale.y + + XMVECTOR originRotationDepth = XMVectorSet(origin.x, origin.y, rotation, layerDepth); + + pImpl->Draw(texture, textureSize, destination, sourceRectangle, color, originRotationDepth, effects); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, XMUINT2 textureSize, FXMVECTOR position, FXMVECTOR color) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 5>(position, g_XMOne); // x, y, 1, 1 + + pImpl->Draw(texture, textureSize, destination, nullptr, color, g_XMZero, 0); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + FXMVECTOR position, + RECT const* sourceRectangle, + FXMVECTOR color, + float rotation, + FXMVECTOR origin, + float scale, + SpriteEffects effects, + float layerDepth) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 4>(position, XMLoadFloat(&scale)); // x, y, scale, scale + + XMVECTOR rotationDepth = XMVectorMergeXY(XMVectorReplicate(rotation), XMVectorReplicate(layerDepth)); + + XMVECTOR originRotationDepth = XMVectorPermute<0, 1, 4, 5>(origin, rotationDepth); + + pImpl->Draw(texture, textureSize, destination, sourceRectangle, color, originRotationDepth, effects); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + FXMVECTOR position, + RECT const* sourceRectangle, + FXMVECTOR color, + float rotation, + FXMVECTOR origin, + GXMVECTOR scale, + SpriteEffects effects, + float layerDepth) +{ + XMVECTOR destination = XMVectorPermute<0, 1, 4, 5>(position, scale); // x, y, scale.x, scale.y + + XMVECTOR rotationDepth = XMVectorMergeXY(XMVectorReplicate(rotation), XMVectorReplicate(layerDepth)); + + XMVECTOR originRotationDepth = XMVectorPermute<0, 1, 4, 5>(origin, rotationDepth); + + pImpl->Draw(texture, textureSize, destination, sourceRectangle, color, originRotationDepth, effects); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + RECT const& destinationRectangle, + FXMVECTOR color) +{ + XMVECTOR destination = LoadRect(&destinationRectangle); // x, y, w, h + + pImpl->Draw(texture, textureSize, destination, nullptr, color, g_XMZero, Impl::SpriteInfo::DestSizeInPixels); +} + + +_Use_decl_annotations_ +void XM_CALLCONV SpriteBatch::Draw(D3D12_GPU_DESCRIPTOR_HANDLE texture, + XMUINT2 textureSize, + RECT const& destinationRectangle, + RECT const* sourceRectangle, + FXMVECTOR color, + float rotation, + XMFLOAT2 const& origin, + SpriteEffects effects, + float layerDepth) +{ + XMVECTOR destination = LoadRect(&destinationRectangle); // x, y, w, h + + XMVECTOR originRotationDepth = XMVectorSet(origin.x, origin.y, rotation, layerDepth); + + pImpl->Draw(texture, textureSize, destination, sourceRectangle, color, originRotationDepth, effects | Impl::SpriteInfo::DestSizeInPixels); +} + + +void SpriteBatch::SetRotation(DXGI_MODE_ROTATION mode) +{ + pImpl->mRotation = mode; +} + + +DXGI_MODE_ROTATION SpriteBatch::GetRotation() const +{ + return pImpl->mRotation; +} + + +void SpriteBatch::SetViewport(const D3D12_VIEWPORT& viewPort) +{ + pImpl->mSetViewport = true; + pImpl->mViewPort = viewPort; +} diff --git a/Kits/DirectXTK12/Src/SpriteFont.cpp b/Kits/DirectXTK12/Src/SpriteFont.cpp new file mode 100644 index 00000000..07e2b4d3 --- /dev/null +++ b/Kits/DirectXTK12/Src/SpriteFont.cpp @@ -0,0 +1,532 @@ +//-------------------------------------------------------------------------------------- +// File: SpriteFont.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" + +#include +#include + +#include "SpriteFont.h" +#include "DirectXHelpers.h" +#include "BinaryReader.h" +#include "ResourceUploadBatch.h" +#include "DescriptorHeap.h" + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + + +// Internal SpriteFont implementation class. +class SpriteFont::Impl +{ +public: + Impl(_In_ ID3D12Device* device, + _In_ ResourceUploadBatch& upload, + _In_ BinaryReader* reader, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE cpuDesc, + _In_ D3D12_GPU_DESCRIPTOR_HANDLE gpuDesc); + Impl(_In_ D3D12_GPU_DESCRIPTOR_HANDLE texture, + _In_ XMUINT2 textureSize, + _In_reads_(glyphCount) Glyph const* glyphs, + _In_ size_t glyphCount, + _In_ float lineSpacing); + + Glyph const* FindGlyph(wchar_t character) const; + + void SetDefaultCharacter(wchar_t character); + + template + void ForEachGlyph(_In_z_ wchar_t const* text, TAction action) const; + + void CreateTextureResource(_In_ ID3D12Device* device, + _In_ ResourceUploadBatch& upload, + _In_ uint32_t width, _In_ uint32_t height, + _In_ DXGI_FORMAT format, + _In_ uint32_t stride, _In_ uint32_t rows, + _In_reads_(stride * rows) const uint8_t* data); + + // Fields. + ComPtr textureResource; + D3D12_GPU_DESCRIPTOR_HANDLE texture; + XMUINT2 textureSize; + std::vector glyphs; + Glyph const* defaultGlyph; + float lineSpacing; +}; + + +// Constants. +const XMFLOAT2 SpriteFont::Float2Zero(0, 0); + +static const char spriteFontMagic[] = "DXTKfont"; + + +// Comparison operators make our sorted glyph vector work with std::binary_search and lower_bound. +namespace DirectX +{ + static inline bool operator< (SpriteFont::Glyph const& left, SpriteFont::Glyph const& right) + { + return left.Character < right.Character; + } + + static inline bool operator< (wchar_t left, SpriteFont::Glyph const& right) + { + return left < right.Character; + } + + static inline bool operator< (SpriteFont::Glyph const& left, wchar_t right) + { + return left.Character < right; + } +} + + +// Reads a SpriteFont from the binary format created by the MakeSpriteFont utility. +_Use_decl_annotations_ +SpriteFont::Impl::Impl( + ID3D12Device* device, + ResourceUploadBatch& upload, + BinaryReader* reader, + D3D12_CPU_DESCRIPTOR_HANDLE cpuDesc, + D3D12_GPU_DESCRIPTOR_HANDLE gpuDesc) +{ + // Validate the header. + for (char const* magic = spriteFontMagic; *magic; magic++) + { + if (reader->Read() != *magic) + { + DebugTrace( "SpriteFont provided with an invalid .spritefont file\n" ); + throw std::exception("Not a MakeSpriteFont output binary"); + } + } + + // Read the glyph data. + auto glyphCount = reader->Read(); + auto glyphData = reader->ReadArray(glyphCount); + + glyphs.assign(glyphData, glyphData + glyphCount); + + // Read font properties. + lineSpacing = reader->Read(); + + SetDefaultCharacter((wchar_t)reader->Read()); + + // Read the texture data. + auto textureWidth = reader->Read(); + auto textureHeight = reader->Read(); + auto textureFormat = reader->Read(); + auto textureStride = reader->Read(); + auto textureRows = reader->Read(); + auto textureData = reader->ReadArray(textureStride * textureRows); + + // Create the D3D texture object. + CreateTextureResource( + device, upload, + textureWidth, textureHeight, + textureFormat, + textureStride, textureRows, + textureData ); + + // Create the shader resource view + CreateShaderResourceView( + device, textureResource.Get(), + cpuDesc, false); + + // Save off the GPU descriptor pointer and size. + texture = gpuDesc; + textureSize = XMUINT2(textureWidth, textureHeight); +} + + +// Constructs a SpriteFont from arbitrary user specified glyph data. +_Use_decl_annotations_ +SpriteFont::Impl::Impl(D3D12_GPU_DESCRIPTOR_HANDLE texture, XMUINT2 textureSize, Glyph const* glyphs, size_t glyphCount, float lineSpacing) + : texture(texture), + textureSize(textureSize), + glyphs(glyphs, glyphs + glyphCount), + lineSpacing(lineSpacing), + defaultGlyph(nullptr) +{ + if (!std::is_sorted(glyphs, glyphs + glyphCount)) + { + throw std::exception("Glyphs must be in ascending codepoint order"); + } +} + + +// Looks up the requested glyph, falling back to the default character if it is not in the font. +SpriteFont::Glyph const* SpriteFont::Impl::FindGlyph(wchar_t character) const +{ + auto glyph = std::lower_bound(glyphs.begin(), glyphs.end(), character); + + if (glyph != glyphs.end() && glyph->Character == character) + { + return &*glyph; + } + + if (defaultGlyph) + { + return defaultGlyph; + } + + DebugTrace( "SpriteFont encountered a character not in the font (%u, %C), and no default glyph was provided\n", character, character ); + throw std::exception("Character not in font"); +} + + +// Sets the missing-character fallback glyph. +void SpriteFont::Impl::SetDefaultCharacter(wchar_t character) +{ + defaultGlyph = nullptr; + + if (character) + { + defaultGlyph = FindGlyph(character); + } +} + + +// The core glyph layout algorithm, shared between DrawString and MeasureString. +template +void SpriteFont::Impl::ForEachGlyph(_In_z_ wchar_t const* text, TAction action) const +{ + float x = 0; + float y = 0; + + for (; *text; text++) + { + wchar_t character = *text; + + switch (character) + { + case '\r': + // Skip carriage returns. + continue; + + case '\n': + // New line. + x = 0; + y += lineSpacing; + break; + + default: + // Output this character. + auto glyph = FindGlyph(character); + + x += glyph->XOffset; + + if (x < 0) + x = 0; + + float advance = glyph->Subrect.right - glyph->Subrect.left + glyph->XAdvance; + + if ( !iswspace(character) + || ( ( glyph->Subrect.right - glyph->Subrect.left ) > 1 ) + || ( ( glyph->Subrect.bottom - glyph->Subrect.top ) > 1 ) ) + { + action(glyph, x, y, advance); + } + + x += advance; + break; + } + } +} + + +_Use_decl_annotations_ +void SpriteFont::Impl::CreateTextureResource( + ID3D12Device* device, + ResourceUploadBatch& upload, + uint32_t width, uint32_t height, + DXGI_FORMAT format, + uint32_t stride, uint32_t rows, + const uint8_t* data) +{ + D3D12_RESOURCE_DESC desc = {}; + desc.Width = static_cast(width); + desc.Height = static_cast(height); + desc.MipLevels = 1; + desc.DepthOrArraySize = 1; + desc.Format = format; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + ThrowIfFailed(device->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(textureResource.ReleaseAndGetAddressOf()))); + + SetDebugObjectName(textureResource.Get(), L"SpriteFont:Texture"); + + D3D12_SUBRESOURCE_DATA subres = {}; + subres.pData = data; + subres.RowPitch = stride; + subres.SlicePitch = stride * rows; + + upload.Upload( + textureResource.Get(), + 0, + &subres, + 1); + + upload.Transition( + textureResource.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); +} + + +// Construct from a binary file created by the MakeSpriteFont utility. +_Use_decl_annotations_ +SpriteFont::SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, wchar_t const* fileName, D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorDest) +{ + BinaryReader reader(fileName); + + pImpl = std::make_unique(device, upload, &reader, cpuDescriptorDest, gpuDescriptorDest); +} + + +// Construct from a binary blob created by the MakeSpriteFont utility and already loaded into memory. +_Use_decl_annotations_ +SpriteFont::SpriteFont(ID3D12Device* device, ResourceUploadBatch& upload, uint8_t const* dataBlob, size_t dataSize, D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorDest, D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorDest) +{ + BinaryReader reader(dataBlob, dataSize); + + pImpl = std::make_unique(device, upload, &reader, cpuDescriptorDest, gpuDescriptorDest); +} + + +// Construct from arbitrary user specified glyph data (for those not using the MakeSpriteFont utility). +SpriteFont::SpriteFont(_In_ D3D12_GPU_DESCRIPTOR_HANDLE texture, _In_ XMUINT2 textureSize, _In_reads_(glyphCount) Glyph const* glyphs, _In_ size_t glyphCount, _In_ float lineSpacing) + : pImpl(new Impl(texture, textureSize, glyphs, glyphCount, lineSpacing)) +{ +} + + +// Move constructor. +SpriteFont::SpriteFont(SpriteFont&& moveFrom) + : pImpl(std::move(moveFrom.pImpl)) +{ +} + + +// Move assignment. +SpriteFont& SpriteFont::operator= (SpriteFont&& moveFrom) +{ + pImpl = std::move(moveFrom.pImpl); + return *this; +} + + +// Public destructor. +SpriteFont::~SpriteFont() +{ +} + + +void XM_CALLCONV SpriteFont::DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, float scale, SpriteEffects effects, float layerDepth) const +{ + DrawString(spriteBatch, text, XMLoadFloat2(&position), color, rotation, XMLoadFloat2(&origin), XMVectorReplicate(scale), effects, layerDepth); +} + + +void XM_CALLCONV SpriteFont::DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, XMFLOAT2 const& position, FXMVECTOR color, float rotation, XMFLOAT2 const& origin, XMFLOAT2 const& scale, SpriteEffects effects, float layerDepth) const +{ + DrawString(spriteBatch, text, XMLoadFloat2(&position), color, rotation, XMLoadFloat2(&origin), XMLoadFloat2(&scale), effects, layerDepth); +} + + +void XM_CALLCONV SpriteFont::DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, float scale, SpriteEffects effects, float layerDepth) const +{ + DrawString(spriteBatch, text, position, color, rotation, origin, XMVectorReplicate(scale), effects, layerDepth); +} + + +void XM_CALLCONV SpriteFont::DrawString(_In_ SpriteBatch* spriteBatch, _In_z_ wchar_t const* text, FXMVECTOR position, FXMVECTOR color, float rotation, FXMVECTOR origin, GXMVECTOR scale, SpriteEffects effects, float layerDepth) const +{ + static_assert(SpriteEffects_FlipHorizontally == 1 && + SpriteEffects_FlipVertically == 2, "If you change these enum values, the following tables must be updated to match"); + + // Lookup table indicates which way to move along each axis per SpriteEffects enum value. + static XMVECTORF32 axisDirectionTable[4] = + { + { -1, -1 }, + { 1, -1 }, + { -1, 1 }, + { 1, 1 }, + }; + + // Lookup table indicates which axes are mirrored for each SpriteEffects enum value. + static XMVECTORF32 axisIsMirroredTable[4] = + { + { 0, 0 }, + { 1, 0 }, + { 0, 1 }, + { 1, 1 }, + }; + + XMVECTOR baseOffset = origin; + + // If the text is mirrored, offset the start position accordingly. + if (effects) + { + baseOffset -= MeasureString(text) * axisIsMirroredTable[effects & 3]; + } + + // Draw each character in turn. + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) + { + UNREFERENCED_PARAMETER(advance); + + XMVECTOR offset = XMVectorMultiplyAdd(XMVectorSet(x, y + glyph->YOffset, 0, 0), axisDirectionTable[effects & 3], baseOffset); + + if (effects) + { + // For mirrored characters, specify bottom and/or right instead of top left. + XMVECTOR glyphRect = XMConvertVectorIntToFloat(XMLoadInt4(reinterpret_cast(&glyph->Subrect)), 0); + + // xy = glyph width/height. + glyphRect = XMVectorSwizzle<2, 3, 0, 1>(glyphRect) - glyphRect; + + offset = XMVectorMultiplyAdd(glyphRect, axisIsMirroredTable[effects & 3], offset); + } + + spriteBatch->Draw(pImpl->texture, pImpl->textureSize, position, &glyph->Subrect, color, rotation, offset, scale, effects, layerDepth); + }); +} + + +XMVECTOR XM_CALLCONV SpriteFont::MeasureString(_In_z_ wchar_t const* text) const +{ + XMVECTOR result = XMVectorZero(); + + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) + { + UNREFERENCED_PARAMETER(advance); + + float w = (float)(glyph->Subrect.right - glyph->Subrect.left); + float h = (float)(glyph->Subrect.bottom - glyph->Subrect.top) + glyph->YOffset; + + h = std::max(h, pImpl->lineSpacing); + + result = XMVectorMax(result, XMVectorSet(x + w, y + h, 0, 0)); + }); + + return result; +} + + +RECT SpriteFont::MeasureDrawBounds(_In_z_ wchar_t const* text, XMFLOAT2 const& position) const +{ + RECT result = { LONG_MAX, LONG_MAX, 0, 0 }; + + pImpl->ForEachGlyph(text, [&](Glyph const* glyph, float x, float y, float advance) + { + float w = (float)(glyph->Subrect.right - glyph->Subrect.left); + float h = (float)(glyph->Subrect.bottom - glyph->Subrect.top); + + float minX = position.x + x; + float minY = position.y + y + glyph->YOffset; + + float maxX = std::max(minX + advance, minX + w); + float maxY = minY + h; + + if (minX < result.left) + result.left = long(minX); + + if (minY < result.top) + result.top = long(minY); + + if (result.right < maxX) + result.right = long(maxX); + + if (result.bottom < maxY) + result.bottom = long(maxY); + }); + + if (result.left == LONG_MAX) + { + result.left = 0; + result.top = 0; + } + + return result; +} + + +RECT XM_CALLCONV SpriteFont::MeasureDrawBounds(_In_z_ wchar_t const* text, FXMVECTOR position) const +{ + XMFLOAT2 pos; + XMStoreFloat2(&pos, position); + + return MeasureDrawBounds(text, pos); +} + + +// Spacing properties +float SpriteFont::GetLineSpacing() const +{ + return pImpl->lineSpacing; +} + + +void SpriteFont::SetLineSpacing(float spacing) +{ + pImpl->lineSpacing = spacing; +} + + +// Font properties +wchar_t SpriteFont::GetDefaultCharacter() const +{ + return pImpl->defaultGlyph ? (wchar_t)pImpl->defaultGlyph->Character : 0; +} + + +void SpriteFont::SetDefaultCharacter(wchar_t character) +{ + pImpl->SetDefaultCharacter(character); +} + + +bool SpriteFont::ContainsCharacter(wchar_t character) const +{ + return std::binary_search(pImpl->glyphs.begin(), pImpl->glyphs.end(), character); +} + + +// Custom layout/rendering +SpriteFont::Glyph const* SpriteFont::FindGlyph(wchar_t character) const +{ + return pImpl->FindGlyph(character); +} + + +D3D12_GPU_DESCRIPTOR_HANDLE SpriteFont::GetSpriteSheet() const +{ + return pImpl->texture; +} + + +XMUINT2 SpriteFont::GetSpriteSheetSize() const +{ + return pImpl->textureSize; +} diff --git a/Kits/DirectXTK12/Src/TeapotData.inc b/Kits/DirectXTK12/Src/TeapotData.inc new file mode 100644 index 00000000..00def9c9 --- /dev/null +++ b/Kits/DirectXTK12/Src/TeapotData.inc @@ -0,0 +1,185 @@ +//-------------------------------------------------------------------------------------- +// File: TeapotData.inc +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + + +// The teapot model consists of 10 bezier patches. Each patch has 16 control +// points, plus a flag indicating whether it should be mirrored in the Z axis +// as well as in X (all of the teapot is symmetrical from left to right, but +// only some parts are symmetrical from front to back). The control points +// are stored as integer indices into the TeapotControlPoints array. + +struct TeapotPatch +{ + bool mirrorZ; + int indices[16]; +}; + + +// Static data array defines the bezier patches that make up the teapot. +const TeapotPatch TeapotPatches[] = +{ + // Rim. + { true, { 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + + // Body. + { true, { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 } }, + { true, { 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 } }, + + // Lid. + { true, { 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3 } }, + { true, { 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117 } }, + + // Handle. + { false, { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 } }, + { false, { 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67 } }, + + // Spout. + { false, { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83 } }, + { false, { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 } }, + + // Bottom. + { true, { 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37 } }, +}; + + +// Static array defines the control point positions that make up the teapot. +const DirectX::XMVECTORF32 TeapotControlPoints[] = +{ + { 0, 0.345f, -0.05f }, + { -0.028f, 0.345f, -0.05f }, + { -0.05f, 0.345f, -0.028f }, + { -0.05f, 0.345f, -0 }, + { 0, 0.3028125f, -0.334375f }, + { -0.18725f, 0.3028125f, -0.334375f }, + { -0.334375f, 0.3028125f, -0.18725f }, + { -0.334375f, 0.3028125f, -0 }, + { 0, 0.3028125f, -0.359375f }, + { -0.20125f, 0.3028125f, -0.359375f }, + { -0.359375f, 0.3028125f, -0.20125f }, + { -0.359375f, 0.3028125f, -0 }, + { 0, 0.27f, -0.375f }, + { -0.21f, 0.27f, -0.375f }, + { -0.375f, 0.27f, -0.21f }, + { -0.375f, 0.27f, -0 }, + { 0, 0.13875f, -0.4375f }, + { -0.245f, 0.13875f, -0.4375f }, + { -0.4375f, 0.13875f, -0.245f }, + { -0.4375f, 0.13875f, -0 }, + { 0, 0.007499993f, -0.5f }, + { -0.28f, 0.007499993f, -0.5f }, + { -0.5f, 0.007499993f, -0.28f }, + { -0.5f, 0.007499993f, -0 }, + { 0, -0.105f, -0.5f }, + { -0.28f, -0.105f, -0.5f }, + { -0.5f, -0.105f, -0.28f }, + { -0.5f, -0.105f, -0 }, + { 0, -0.105f, 0.5f }, + { 0, -0.2175f, -0.5f }, + { -0.28f, -0.2175f, -0.5f }, + { -0.5f, -0.2175f, -0.28f }, + { -0.5f, -0.2175f, -0 }, + { 0, -0.27375f, -0.375f }, + { -0.21f, -0.27375f, -0.375f }, + { -0.375f, -0.27375f, -0.21f }, + { -0.375f, -0.27375f, -0 }, + { 0, -0.2925f, -0.375f }, + { -0.21f, -0.2925f, -0.375f }, + { -0.375f, -0.2925f, -0.21f }, + { -0.375f, -0.2925f, -0 }, + { 0, 0.17625f, 0.4f }, + { -0.075f, 0.17625f, 0.4f }, + { -0.075f, 0.2325f, 0.375f }, + { 0, 0.2325f, 0.375f }, + { 0, 0.17625f, 0.575f }, + { -0.075f, 0.17625f, 0.575f }, + { -0.075f, 0.2325f, 0.625f }, + { 0, 0.2325f, 0.625f }, + { 0, 0.17625f, 0.675f }, + { -0.075f, 0.17625f, 0.675f }, + { -0.075f, 0.2325f, 0.75f }, + { 0, 0.2325f, 0.75f }, + { 0, 0.12f, 0.675f }, + { -0.075f, 0.12f, 0.675f }, + { -0.075f, 0.12f, 0.75f }, + { 0, 0.12f, 0.75f }, + { 0, 0.06375f, 0.675f }, + { -0.075f, 0.06375f, 0.675f }, + { -0.075f, 0.007499993f, 0.75f }, + { 0, 0.007499993f, 0.75f }, + { 0, -0.04875001f, 0.625f }, + { -0.075f, -0.04875001f, 0.625f }, + { -0.075f, -0.09562501f, 0.6625f }, + { 0, -0.09562501f, 0.6625f }, + { -0.075f, -0.105f, 0.5f }, + { -0.075f, -0.18f, 0.475f }, + { 0, -0.18f, 0.475f }, + { 0, 0.02624997f, -0.425f }, + { -0.165f, 0.02624997f, -0.425f }, + { -0.165f, -0.18f, -0.425f }, + { 0, -0.18f, -0.425f }, + { 0, 0.02624997f, -0.65f }, + { -0.165f, 0.02624997f, -0.65f }, + { -0.165f, -0.12375f, -0.775f }, + { 0, -0.12375f, -0.775f }, + { 0, 0.195f, -0.575f }, + { -0.0625f, 0.195f, -0.575f }, + { -0.0625f, 0.17625f, -0.6f }, + { 0, 0.17625f, -0.6f }, + { 0, 0.27f, -0.675f }, + { -0.0625f, 0.27f, -0.675f }, + { -0.0625f, 0.27f, -0.825f }, + { 0, 0.27f, -0.825f }, + { 0, 0.28875f, -0.7f }, + { -0.0625f, 0.28875f, -0.7f }, + { -0.0625f, 0.2934375f, -0.88125f }, + { 0, 0.2934375f, -0.88125f }, + { 0, 0.28875f, -0.725f }, + { -0.0375f, 0.28875f, -0.725f }, + { -0.0375f, 0.298125f, -0.8625f }, + { 0, 0.298125f, -0.8625f }, + { 0, 0.27f, -0.7f }, + { -0.0375f, 0.27f, -0.7f }, + { -0.0375f, 0.27f, -0.8f }, + { 0, 0.27f, -0.8f }, + { 0, 0.4575f, -0 }, + { 0, 0.4575f, -0.2f }, + { -0.1125f, 0.4575f, -0.2f }, + { -0.2f, 0.4575f, -0.1125f }, + { -0.2f, 0.4575f, -0 }, + { 0, 0.3825f, -0 }, + { 0, 0.27f, -0.35f }, + { -0.196f, 0.27f, -0.35f }, + { -0.35f, 0.27f, -0.196f }, + { -0.35f, 0.27f, -0 }, + { 0, 0.3075f, -0.1f }, + { -0.056f, 0.3075f, -0.1f }, + { -0.1f, 0.3075f, -0.056f }, + { -0.1f, 0.3075f, -0 }, + { 0, 0.3075f, -0.325f }, + { -0.182f, 0.3075f, -0.325f }, + { -0.325f, 0.3075f, -0.182f }, + { -0.325f, 0.3075f, -0 }, + { 0, 0.27f, -0.325f }, + { -0.182f, 0.27f, -0.325f }, + { -0.325f, 0.27f, -0.182f }, + { -0.325f, 0.27f, -0 }, + { 0, -0.33f, -0 }, + { -0.1995f, -0.33f, -0.35625f }, + { 0, -0.31125f, -0.375f }, + { 0, -0.33f, -0.35625f }, + { -0.35625f, -0.33f, -0.1995f }, + { -0.375f, -0.31125f, -0 }, + { -0.35625f, -0.33f, -0 }, + { -0.21f, -0.31125f, -0.375f }, + { -0.375f, -0.31125f, -0.21f }, +}; diff --git a/Kits/DirectXTK12/Src/VertexTypes.cpp b/Kits/DirectXTK12/Src/VertexTypes.cpp new file mode 100644 index 00000000..5fbc9f6e --- /dev/null +++ b/Kits/DirectXTK12/Src/VertexTypes.cpp @@ -0,0 +1,166 @@ +//-------------------------------------------------------------------------------------- +// File: VertexTypes.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "VertexTypes.h" + +using namespace DirectX; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position information. +const D3D12_INPUT_ELEMENT_DESC VertexPosition::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert(sizeof(VertexPosition) == 12, "Vertex struct/layout mismatch"); + +const D3D12_INPUT_LAYOUT_DESC VertexPosition::InputLayout = +{ + VertexPosition::InputElements, + VertexPosition::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position and color information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionColor::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionColor) == 28, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionColor::InputLayout = +{ + VertexPositionColor::InputElements, + VertexPositionColor::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position and texture mapping information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionTexture::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionTexture) == 20, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionTexture::InputLayout = +{ + VertexPositionTexture::InputElements, + VertexPositionTexture::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position and dual texture mapping information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionDualTexture::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert(sizeof(VertexPositionDualTexture) == 28, "Vertex struct/layout mismatch"); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionDualTexture::InputLayout = +{ + VertexPositionDualTexture::InputElements, + VertexPositionDualTexture::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position and normal vector. +const D3D12_INPUT_ELEMENT_DESC VertexPositionNormal::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionNormal) == 24, "Vertex struct/layout mismatch" ); + + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position, color, and texture mapping information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionColorTexture::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionColorTexture) == 36, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionColorTexture::InputLayout = +{ + VertexPositionColorTexture::InputElements, + VertexPositionColorTexture::InputElementCount +}; + + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position, normal vector, and color information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionNormalColor::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionNormalColor) == 40, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionNormalColor::InputLayout = +{ + VertexPositionNormalColor::InputElements, + VertexPositionNormalColor::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position, normal vector, and texture mapping information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionNormalTexture::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionNormalTexture) == 32, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionNormalTexture::InputLayout = +{ + VertexPositionNormalTexture::InputElements, + VertexPositionNormalTexture::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// Vertex struct holding position, normal vector, color, and texture mapping information. +const D3D12_INPUT_ELEMENT_DESC VertexPositionNormalColorTexture::InputElements[] = +{ + { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, +}; + +static_assert( sizeof(VertexPositionNormalColorTexture) == 48, "Vertex struct/layout mismatch" ); + +const D3D12_INPUT_LAYOUT_DESC VertexPositionNormalColorTexture::InputLayout = +{ + VertexPositionNormalColorTexture::InputElements, + VertexPositionNormalColorTexture::InputElementCount +}; + +//-------------------------------------------------------------------------------------- +// VertexPositionNormalTangentColorTexture, VertexPositionNormalTangentColorTextureSkinning are not +// supported for DirectX 12 since they were only present for DGSL \ No newline at end of file diff --git a/Kits/DirectXTK12/Src/WICTextureLoader.cpp b/Kits/DirectXTK12/Src/WICTextureLoader.cpp new file mode 100644 index 00000000..d8da4ded --- /dev/null +++ b/Kits/DirectXTK12/Src/WICTextureLoader.cpp @@ -0,0 +1,693 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader.cpp +// +// Function for loading a WIC image and creating a Direct3D runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for +// auto-gen mipmap support. +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +// We could load multi-frame images (TIFF/GIF) into a texture array. +// For now, we just load the first frame (note: DirectXTex supports multi-frame images) + +#include "pch.h" + +#include "WICTextureLoader.h" + +#include "DirectXHelpers.h" +#include "PlatformHelpers.h" +#include "LoaderHelpers.h" +#include "ResourceUploadBatch.h" + +namespace DirectX +{ + uint32_t CountMips(uint32_t width, uint32_t height); +} + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + //------------------------------------------------------------------------------------- + // WIC Pixel Format Translation Data + //------------------------------------------------------------------------------------- + struct WICTranslate + { + GUID wic; + DXGI_FORMAT format; + }; + + WICTranslate g_WICFormats[] = + { + { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }, + + { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, + + { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, + { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1 + + { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, + + { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, + { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, + + { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, + { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, + { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, + { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, + + { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, + + { GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT }, // WIC 2 + }; + + //------------------------------------------------------------------------------------- + // WIC Pixel Format nearest conversion table + //------------------------------------------------------------------------------------- + + struct WICConvert + { + GUID source; + GUID target; + }; + + WICConvert g_WICConvert[] = + { + // Note target GUID in this conversion table must be one of those directly supported formats (above). + + { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM + + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM (WIC2) + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM (WIC2) + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT (WIC2) + + { GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat96bppRGBFloat }, // DXGI_FORMAT_R32G32B32_FLOAT (WIC2) + + // We don't support n-channel formats + }; +} + +//-------------------------------------------------------------------------------------- +namespace DirectX +{ + IWICImagingFactory2* _GetWIC() + { + static IWICImagingFactory2* s_Factory = nullptr; + + if (s_Factory) + return s_Factory; + + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&s_Factory)); + if (FAILED(hr)) + { + s_Factory = nullptr; + return nullptr; + } + return s_Factory; + } + +} // namespace DirectX + + +namespace +{ + //--------------------------------------------------------------------------------- + DXGI_FORMAT _WICToDXGI(const GUID& guid) + { + for (size_t i = 0; i < _countof(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0) + return g_WICFormats[i].format; + } + + return DXGI_FORMAT_UNKNOWN; + } + + //--------------------------------------------------------------------------------- + size_t _WICBitsPerPixel(REFGUID targetGuid) + { + auto pWIC = _GetWIC(); + if (!pWIC) + return 0; + + ComPtr cinfo; + if (FAILED(pWIC->CreateComponentInfo(targetGuid, cinfo.GetAddressOf()))) + return 0; + + WICComponentType type; + if (FAILED(cinfo->GetComponentType(&type))) + return 0; + + if (type != WICPixelFormat) + return 0; + + ComPtr pfinfo; + if (FAILED(cinfo.As(&pfinfo))) + return 0; + + UINT bpp; + if (FAILED(pfinfo->GetBitsPerPixel(&bpp))) + return 0; + + return bpp; + } + + //--------------------------------------------------------------------------------- + HRESULT CreateTextureFromWIC(_In_ ID3D12Device* d3dDevice, + _In_ ResourceUploadBatch& resourceUpload, + _In_ IWICBitmapFrameDecode *frame, + _In_ size_t maxsize, + _In_ D3D12_RESOURCE_FLAGS flags, + _In_ bool forceSRGB, + _In_ bool generateMips, + _Outptr_ ID3D12Resource** texture) + { + UINT width, height; + HRESULT hr = frame->GetSize(&width, &height); + if (FAILED(hr)) + return hr; + + assert(width > 0 && height > 0); + + if (!maxsize) + { + maxsize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; + } + + assert(maxsize > 0); + + UINT twidth, theight; + if (width > maxsize || height > maxsize) + { + float ar = static_cast(height) / static_cast(width); + if (width > height) + { + twidth = static_cast(maxsize); + theight = static_cast(static_cast(maxsize) * ar); + } + else + { + theight = static_cast(maxsize); + twidth = static_cast(static_cast(maxsize) / ar); + } + assert(twidth <= maxsize && theight <= maxsize); + } + else + { + twidth = width; + theight = height; + } + + // Determine format + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID convertGUID; + memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID)); + + size_t bpp = 0; + + DXGI_FORMAT format = _WICToDXGI(pixelFormat); + if (format == DXGI_FORMAT_UNKNOWN) + { + for (size_t i = 0; i < _countof(g_WICConvert); ++i) + { + if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID)); + + format = _WICToDXGI(g_WICConvert[i].target); + assert(format != DXGI_FORMAT_UNKNOWN); + bpp = _WICBitsPerPixel(convertGUID); + break; + } + } + + if (format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + else + { + bpp = _WICBitsPerPixel(pixelFormat); + } + + if (!bpp) + return E_FAIL; + + // Handle sRGB formats + if (forceSRGB) + { + format = MakeSRGB(format); + } + else + { + ComPtr metareader; + if (SUCCEEDED(frame->GetMetadataQueryReader(metareader.GetAddressOf()))) + { + GUID containerFormat; + if (SUCCEEDED(metareader->GetContainerFormat(&containerFormat))) + { + // Check for sRGB colorspace metadata + bool sRGB = false; + + PROPVARIANT value; + PropVariantInit(&value); + + if (memcmp(&containerFormat, &GUID_ContainerFormatPng, sizeof(GUID)) == 0) + { + // Check for sRGB chunk + if (SUCCEEDED(metareader->GetMetadataByName(L"/sRGB/RenderingIntent", &value)) && value.vt == VT_UI1) + { + sRGB = true; + } + } +#if defined(_XBOX_ONE) && defined(_TITLE) + else if (memcmp(&containerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID)) == 0) + { + if (SUCCEEDED(metareader->GetMetadataByName(L"/app1/ifd/exif/{ushort=40961}", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } + } + else if (memcmp(&containerFormat, &GUID_ContainerFormatTiff, sizeof(GUID)) == 0) + { + if (SUCCEEDED(metareader->GetMetadataByName(L"/ifd/exif/{ushort=40961}", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } + } +#else + else if (SUCCEEDED(metareader->GetMetadataByName(L"System.Image.ColorSpace", &value)) && value.vt == VT_UI2 && value.uiVal == 1) + { + sRGB = true; + } +#endif + + PropVariantClear(&value); + + if (sRGB) + format = MakeSRGB(format); + } + } + } + + // Verify our target format is supported by the current device + // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) + D3D12_FEATURE_DATA_FORMAT_SUPPORT support = {}; + support.Format = format; + hr = d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support)); + if (FAILED(hr) || !(support.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) + { + // Fallback to RGBA 32-bit format which is supported by all devices + memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)); + format = DXGI_FORMAT_R8G8B8A8_UNORM; + bpp = 32; + } + + // Allocate temporary memory for image + size_t rowPitch = (twidth * bpp + 7) / 8; + size_t imageSize = rowPitch * theight; + + std::unique_ptr temp(new (std::nothrow) uint8_t[imageSize]); + if (!temp) + return E_OUTOFMEMORY; + + // Load image data + if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0 + && twidth == width + && theight == height) + { + // No format conversion or resize needed + hr = frame->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + else if (twidth != width || theight != height) + { + // Resize + auto pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0) + { + // No format conversion needed + hr = scaler->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + } + else + { + // Format conversion but no resize + auto pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + + // Count the number of mips + uint32_t mipCount = (generateMips) ? CountMips(twidth, theight) : 1; + + // Create texture + D3D12_RESOURCE_DESC desc = {}; + desc.Width = twidth; + desc.Height = theight; + desc.MipLevels = (uint16_t)mipCount; + desc.DepthOrArraySize = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Flags = flags; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + ID3D12Resource* tex = nullptr; + hr = d3dDevice->CreateCommittedResource( + &defaultHeapProperties, + D3D12_HEAP_FLAG_NONE, + &desc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_GRAPHICS_PPV_ARGS(&tex)); + + if (FAILED(hr)) + { + return hr; + } + + _Analysis_assume_(tex != 0); + + // Upload the texture data + D3D12_SUBRESOURCE_DATA initData; + initData.pData = temp.get(); + initData.RowPitch = static_cast(rowPitch); + initData.SlicePitch = static_cast(imageSize); + + resourceUpload.Upload( + tex, + 0, + &initData, + 1); + + resourceUpload.Transition( + tex, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + // Generate mips? + if (generateMips) + { + resourceUpload.GenerateMips(tex); + } + + *texture = tex; + return hr; + } +} // anonymous namespace + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromMemory( ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const uint8_t* wicData, + size_t wicDataSize, + ID3D12Resource** texture, + bool generateMips, + size_t maxsize ) +{ + return CreateWICTextureFromMemoryEx( d3dDevice, resourceUpload, wicData, wicDataSize, maxsize, + D3D12_RESOURCE_FLAG_NONE, false, generateMips, + texture ); +} + + +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromMemoryEx( ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const uint8_t* wicData, + size_t wicDataSize, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool generateMips, + ID3D12Resource** texture ) +{ + if ( texture ) + { + *texture = nullptr; + } + + if (!d3dDevice || !wicData || !texture) + return E_INVALIDARG; + + if ( !wicDataSize ) + return E_FAIL; + +#ifdef _M_AMD64 + if ( wicDataSize > 0xFFFFFFFF ) + return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE ); +#endif + + auto pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + // Create input stream for memory + ComPtr stream; + HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = stream->InitializeFromMemory( const_cast( wicData ), static_cast( wicDataSize ) ); + if ( FAILED(hr) ) + return hr; + + // Initialize WIC + ComPtr decoder; + hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + ComPtr frame; + hr = decoder->GetFrame( 0, frame.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = CreateTextureFromWIC( d3dDevice, resourceUpload, + frame.Get(), maxsize, + flags, forceSRGB, + generateMips, texture ); + if ( FAILED(hr)) + return hr; + + _Analysis_assume_(*texture != nullptr); + SetDebugObjectName(*texture, L"WICTextureLoader"); + + return hr; +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromFile( ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const wchar_t* fileName, + ID3D12Resource** texture, + bool generateMips, + size_t maxsize ) +{ + return CreateWICTextureFromFileEx( d3dDevice, resourceUpload, fileName, maxsize, + D3D12_RESOURCE_FLAG_NONE, false, generateMips, + texture ); +} + + +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromFileEx( ID3D12Device* d3dDevice, + ResourceUploadBatch& resourceUpload, + const wchar_t* fileName, + size_t maxsize, + D3D12_RESOURCE_FLAGS flags, + bool forceSRGB, + bool generateMips, + ID3D12Resource** texture ) +{ + if ( texture ) + { + *texture = nullptr; + } + + if (!d3dDevice || !fileName || !texture ) + return E_INVALIDARG; + + auto pWIC = _GetWIC(); + if ( !pWIC ) + return E_NOINTERFACE; + + // Initialize WIC + ComPtr decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + ComPtr frame; + hr = decoder->GetFrame( 0, frame.GetAddressOf() ); + if ( FAILED(hr) ) + return hr; + + hr = CreateTextureFromWIC( d3dDevice, resourceUpload, + frame.Get(), maxsize, + flags, forceSRGB, + generateMips, texture ); + +#if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) ) + if ( SUCCEEDED(hr) ) + { + const wchar_t* pstrName = wcsrchr(fileName, '\\' ); + if (!pstrName) + { + pstrName = fileName; + } + else + { + pstrName++; + } + + if (texture != 0 && *texture != 0) + { + (*texture)->SetName(pstrName); + } + } +#endif + + return hr; +} + diff --git a/Kits/DirectXTK12/Src/d3dx12.h b/Kits/DirectXTK12/Src/d3dx12.h new file mode 100644 index 00000000..82f35e76 --- /dev/null +++ b/Kits/DirectXTK12/Src/d3dx12.h @@ -0,0 +1,1534 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#ifndef __D3DX12_H__ +#define __D3DX12_H__ + +#include + +#if defined( __cplusplus ) + +struct CD3DX12_DEFAULT {}; +extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT; + +//------------------------------------------------------------------------------------------------ +inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ + return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width && + l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth; +} + +//------------------------------------------------------------------------------------------------ +inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RECT : public D3D12_RECT +{ + CD3DX12_RECT() + {} + explicit CD3DX12_RECT( const D3D12_RECT& o ) : + D3D12_RECT( o ) + {} + explicit CD3DX12_RECT( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + right = Right; + bottom = Bottom; + } + ~CD3DX12_RECT() {} + operator const D3D12_RECT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BOX : public D3D12_BOX +{ + CD3DX12_BOX() + {} + explicit CD3DX12_BOX( const D3D12_BOX& o ) : + D3D12_BOX( o ) + {} + explicit CD3DX12_BOX( + LONG Left, + LONG Right ) + { + left = Left; + top = 0; + front = 0; + right = Right; + bottom = 1; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + front = 0; + right = Right; + bottom = Bottom; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Front, + LONG Right, + LONG Bottom, + LONG Back ) + { + left = Left; + top = Top; + front = Front; + right = Right; + bottom = Bottom; + back = Back; + } + ~CD3DX12_BOX() {} + operator const D3D12_BOX&() const { return *this; } +}; +inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r ) +{ + return l.left == r.left && l.top == r.top && l.front == r.front && + l.right == r.right && l.bottom == r.bottom && l.back == r.back; +} +inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC +{ + CD3DX12_DEPTH_STENCIL_DESC() + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) : + D3D12_DEPTH_STENCIL_DESC( o ) + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) + { + DepthEnable = TRUE; + DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + DepthFunc = D3D12_COMPARISON_FUNC_LESS; + StencilEnable = FALSE; + StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = + { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS }; + FrontFace = defaultStencilOp; + BackFace = defaultStencilOp; + } + explicit CD3DX12_DEPTH_STENCIL_DESC( + BOOL depthEnable, + D3D12_DEPTH_WRITE_MASK depthWriteMask, + D3D12_COMPARISON_FUNC depthFunc, + BOOL stencilEnable, + UINT8 stencilReadMask, + UINT8 stencilWriteMask, + D3D12_STENCIL_OP frontStencilFailOp, + D3D12_STENCIL_OP frontStencilDepthFailOp, + D3D12_STENCIL_OP frontStencilPassOp, + D3D12_COMPARISON_FUNC frontStencilFunc, + D3D12_STENCIL_OP backStencilFailOp, + D3D12_STENCIL_OP backStencilDepthFailOp, + D3D12_STENCIL_OP backStencilPassOp, + D3D12_COMPARISON_FUNC backStencilFunc ) + { + DepthEnable = depthEnable; + DepthWriteMask = depthWriteMask; + DepthFunc = depthFunc; + StencilEnable = stencilEnable; + StencilReadMask = stencilReadMask; + StencilWriteMask = stencilWriteMask; + FrontFace.StencilFailOp = frontStencilFailOp; + FrontFace.StencilDepthFailOp = frontStencilDepthFailOp; + FrontFace.StencilPassOp = frontStencilPassOp; + FrontFace.StencilFunc = frontStencilFunc; + BackFace.StencilFailOp = backStencilFailOp; + BackFace.StencilDepthFailOp = backStencilDepthFailOp; + BackFace.StencilPassOp = backStencilPassOp; + BackFace.StencilFunc = backStencilFunc; + } + ~CD3DX12_DEPTH_STENCIL_DESC() {} + operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC +{ + CD3DX12_BLEND_DESC() + {} + explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) : + D3D12_BLEND_DESC( o ) + {} + explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) + { + AlphaToCoverageEnable = FALSE; + IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + RenderTarget[ i ] = defaultRenderTargetBlendDesc; + } + ~CD3DX12_BLEND_DESC() {} + operator const D3D12_BLEND_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC +{ + CD3DX12_RASTERIZER_DESC() + {} + explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) : + D3D12_RASTERIZER_DESC( o ) + {} + explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + MultisampleEnable = FALSE; + AntialiasedLineEnable = FALSE; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + INT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + BOOL multisampleEnable, + BOOL antialiasedLineEnable, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + MultisampleEnable = multisampleEnable; + AntialiasedLineEnable = antialiasedLineEnable; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + ~CD3DX12_RASTERIZER_DESC() {} + operator const D3D12_RASTERIZER_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO +{ + CD3DX12_RESOURCE_ALLOCATION_INFO() + {} + explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) : + D3D12_RESOURCE_ALLOCATION_INFO( o ) + {} + CD3DX12_RESOURCE_ALLOCATION_INFO( + UINT64 size, + UINT64 alignment ) + { + SizeInBytes = size; + Alignment = alignment; + } + operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES +{ + CD3DX12_HEAP_PROPERTIES() + {} + explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) : + D3D12_HEAP_PROPERTIES(o) + {} + CD3DX12_HEAP_PROPERTIES( + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = D3D12_HEAP_TYPE_CUSTOM; + CPUPageProperty = cpuPageProperty; + MemoryPoolPreference = memoryPoolPreference; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + explicit CD3DX12_HEAP_PROPERTIES( + D3D12_HEAP_TYPE type, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = type; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + operator const D3D12_HEAP_PROPERTIES&() const { return *this; } + bool IsCPUAccessible() const + { + return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM && + (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); + } +}; +inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ + return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && + l.MemoryPoolPreference == r.MemoryPoolPreference && + l.CreationNodeMask == r.CreationNodeMask && + l.VisibleNodeMask == r.VisibleNodeMask; +} +inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC +{ + CD3DX12_HEAP_DESC() + {} + explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) : + D3D12_HEAP_DESC(o) + {} + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_PROPERTIES properties, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = properties; + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_TYPE type, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_PROPERTIES properties, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = properties; + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_TYPE type, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + operator const D3D12_HEAP_DESC&() const { return *this; } + bool IsCPUAccessible() const + { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); } +}; +inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ + return l.SizeInBytes == r.SizeInBytes && + l.Properties == r.Properties && + l.Alignment == r.Alignment && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE +{ + CD3DX12_CLEAR_VALUE() + {} + explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) : + D3D12_CLEAR_VALUE(o) + {} + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + const FLOAT color[4] ) + { + Format = format; + memcpy( Color, color, sizeof( Color ) ); + } + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + FLOAT depth, + UINT8 stencil ) + { + Format = format; + /* Use memcpy to preserve NAN values */ + memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) ); + DepthStencil.Stencil = stencil; + } + operator const D3D12_CLEAR_VALUE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RANGE : public D3D12_RANGE +{ + CD3DX12_RANGE() + {} + explicit CD3DX12_RANGE(const D3D12_RANGE &o) : + D3D12_RANGE(o) + {} + CD3DX12_RANGE( + SIZE_T begin, + SIZE_T end ) + { + Begin = begin; + End = end; + } + operator const D3D12_RANGE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE +{ + CD3DX12_SHADER_BYTECODE() + {} + explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) : + D3D12_SHADER_BYTECODE(o) + {} + CD3DX12_SHADER_BYTECODE( + ID3DBlob* pShaderBlob ) + { + pShaderBytecode = pShaderBlob->GetBufferPointer(); + BytecodeLength = pShaderBlob->GetBufferSize(); + } + CD3DX12_SHADER_BYTECODE( + void* _pShaderBytecode, + SIZE_T bytecodeLength ) + { + pShaderBytecode = _pShaderBytecode; + BytecodeLength = bytecodeLength; + } + operator const D3D12_SHADER_BYTECODE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE +{ + CD3DX12_TILED_RESOURCE_COORDINATE() + {} + explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) : + D3D12_TILED_RESOURCE_COORDINATE(o) + {} + CD3DX12_TILED_RESOURCE_COORDINATE( + UINT x, + UINT y, + UINT z, + UINT subresource ) + { + X = x; + Y = y; + Z = z; + Subresource = subresource; + } + operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE +{ + CD3DX12_TILE_REGION_SIZE() + {} + explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) : + D3D12_TILE_REGION_SIZE(o) + {} + CD3DX12_TILE_REGION_SIZE( + UINT numTiles, + BOOL useBox, + UINT width, + UINT16 height, + UINT16 depth ) + { + NumTiles = numTiles; + UseBox = useBox; + Width = width; + Height = height; + Depth = depth; + } + operator const D3D12_TILE_REGION_SIZE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING +{ + CD3DX12_SUBRESOURCE_TILING() + {} + explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) : + D3D12_SUBRESOURCE_TILING(o) + {} + CD3DX12_SUBRESOURCE_TILING( + UINT widthInTiles, + UINT16 heightInTiles, + UINT16 depthInTiles, + UINT startTileIndexInOverallResource ) + { + WidthInTiles = widthInTiles; + HeightInTiles = heightInTiles; + DepthInTiles = depthInTiles; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_SUBRESOURCE_TILING&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE +{ + CD3DX12_TILE_SHAPE() + {} + explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) : + D3D12_TILE_SHAPE(o) + {} + CD3DX12_TILE_SHAPE( + UINT widthInTexels, + UINT heightInTexels, + UINT depthInTexels ) + { + WidthInTexels = widthInTexels; + HeightInTexels = heightInTexels; + DepthInTexels = depthInTexels; + } + operator const D3D12_TILE_SHAPE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER +{ + CD3DX12_RESOURCE_BARRIER() + {} + explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) : + D3D12_RESOURCE_BARRIER(o) + {} + static inline CD3DX12_RESOURCE_BARRIER Transition( + _In_ ID3D12Resource* pResource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + result.Flags = flags; + barrier.Transition.pResource = pResource; + barrier.Transition.StateBefore = stateBefore; + barrier.Transition.StateAfter = stateAfter; + barrier.Transition.Subresource = subresource; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER Aliasing( + _In_ ID3D12Resource* pResourceBefore, + _In_ ID3D12Resource* pResourceAfter) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = pResourceBefore; + barrier.Aliasing.pResourceAfter = pResourceAfter; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER UAV( + _In_ ID3D12Resource* pResource) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = pResource; + return result; + } + operator const D3D12_RESOURCE_BARRIER&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO +{ + CD3DX12_PACKED_MIP_INFO() + {} + explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) : + D3D12_PACKED_MIP_INFO(o) + {} + CD3DX12_PACKED_MIP_INFO( + UINT8 numStandardMips, + UINT8 numPackedMips, + UINT numTilesForPackedMips, + UINT startTileIndexInOverallResource ) + { + NumStandardMips = numStandardMips; + NumPackedMips = numPackedMips; + NumTilesForPackedMips = numTilesForPackedMips; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_PACKED_MIP_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT +{ + CD3DX12_SUBRESOURCE_FOOTPRINT() + {} + explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) : + D3D12_SUBRESOURCE_FOOTPRINT(o) + {} + CD3DX12_SUBRESOURCE_FOOTPRINT( + DXGI_FORMAT format, + UINT width, + UINT height, + UINT depth, + UINT rowPitch ) + { + Format = format; + Width = width; + Height = height; + Depth = depth; + RowPitch = rowPitch; + } + explicit CD3DX12_SUBRESOURCE_FOOTPRINT( + const D3D12_RESOURCE_DESC& resDesc, + UINT rowPitch ) + { + Format = resDesc.Format; + Width = UINT( resDesc.Width ); + Height = resDesc.Height; + Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1); + RowPitch = rowPitch; + } + operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION +{ + CD3DX12_TEXTURE_COPY_LOCATION() + {} + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + SubresourceIndex = Sub; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE +{ + CD3DX12_DESCRIPTOR_RANGE() { } + explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) : + D3D12_DESCRIPTOR_RANGE(o) + {} + CD3DX12_DESCRIPTOR_RANGE( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) : + D3D12_ROOT_DESCRIPTOR_TABLE(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS +{ + CD3DX12_ROOT_CONSTANTS() {} + explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) : + D3D12_ROOT_CONSTANTS(o) + {} + CD3DX12_ROOT_CONSTANTS( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(num32BitValues, shaderRegister, registerSpace); + } + + inline void Init( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, num32BitValues, shaderRegister, registerSpace); + } + + static inline void Init( + _Out_ D3D12_ROOT_CONSTANTS &rootConstants, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + rootConstants.Num32BitValues = num32BitValues; + rootConstants.ShaderRegister = shaderRegister; + rootConstants.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR +{ + CD3DX12_ROOT_DESCRIPTOR() {} + explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) : + D3D12_ROOT_DESCRIPTOR(o) + {} + CD3DX12_ROOT_DESCRIPTOR( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(shaderRegister, registerSpace); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, shaderRegister, registerSpace); + } + + static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER +{ + CD3DX12_ROOT_PARAMETER() {} + explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) : + D3D12_ROOT_PARAMETER(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace); + } + + static inline void InitAsConstantBufferView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility); + } + + inline void InitAsConstants( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility); + } + + inline void InitAsConstantBufferView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC +{ + CD3DX12_STATIC_SAMPLER_DESC() {} + explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) : + D3D12_STATIC_SAMPLER_DESC(o) + {} + CD3DX12_STATIC_SAMPLER_DESC( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC +{ + CD3DX12_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) : + D3D12_ROOT_SIGNATURE_DESC(o) + {} + CD3DX12_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + desc.NumParameters = numParameters; + desc.pParameters = _pParameters; + desc.NumStaticSamplers = numStaticSamplers; + desc.pStaticSamplers = _pStaticSamplers; + desc.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) : + D3D12_CPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE +{ + CD3DX12_GPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) : + D3D12_GPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + + + diff --git a/Kits/DirectXTK12/Src/dds.h b/Kits/DirectXTK12/Src/dds.h new file mode 100644 index 00000000..3bd63cd9 --- /dev/null +++ b/Kits/DirectXTK12/Src/dds.h @@ -0,0 +1,228 @@ +//-------------------------------------------------------------------------------------- +// dds.h +// +// This header defines constants and structures that are useful when parsing +// DDS files. DDS files were originally designed to use several structures +// and constants that are native to DirectDraw and are defined in ddraw.h, +// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar +// (compatible) constants and structures so that one can use DDS files +// without needing to include ddraw.h. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + + +namespace DirectX +{ + +#pragma pack(push,1) + +const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +struct DDS_PIXELFORMAT +{ + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 )) +#endif /* defined(MAKEFOURCC) */ + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 = + { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V16U16 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION +enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +}; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +struct DDS_HEADER +{ + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; +}; + +struct DDS_HEADER_DXT10 +{ + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 +} ; + +#pragma pack(pop) + +static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); +static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + +} // namespace diff --git a/Kits/DirectXTK12/Src/pch.cpp b/Kits/DirectXTK12/Src/pch.cpp new file mode 100644 index 00000000..f12bcd06 --- /dev/null +++ b/Kits/DirectXTK12/Src/pch.cpp @@ -0,0 +1,14 @@ +//-------------------------------------------------------------------------------------- +// File: pch.cpp +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Kits/DirectXTK12/Src/pch.h b/Kits/DirectXTK12/Src/pch.h new file mode 100644 index 00000000..a9c9e622 --- /dev/null +++ b/Kits/DirectXTK12/Src/pch.h @@ -0,0 +1,78 @@ +//-------------------------------------------------------------------------------------- +// File: pch.h +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#pragma warning(push) +#pragma warning(disable : 4005) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NODRAWTEXT +#define NOGDI +#define NOBITMAP +#define NOMCX +#define NOSERVICE +#define NOHELP +#pragma warning(pop) + +#include + +#ifndef _WIN32_WINNT_WIN10 +#define _WIN32_WINNT_WIN10 0x0A00 +#endif + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include + +#if _XDK_VER < 0x295A044C /* XDK Edition 160200 */ +#error DirectX Tool Kit for Direct3D 12 requires the February 2016 XDK or later +#endif + +#include // core 12.x header +#include // utility 12.x header +#define DCOMMON_H_INCLUDED +#else +#include +#include +#include "d3dx12.h" +#endif + +#if (defined(_XBOX_ONE) && defined(_TITLE)) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) +#include +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include diff --git a/Kits/DirectXTK12/Src/vbo.h b/Kits/DirectXTK12/Src/vbo.h new file mode 100644 index 00000000..5087ed1c --- /dev/null +++ b/Kits/DirectXTK12/Src/vbo.h @@ -0,0 +1,38 @@ +//-------------------------------------------------------------------------------------- +// File: vbo.h +// +// The VBO file format was introduced in the Windows 8.0 ResourceLoading sample. It's +// a simple binary file containing a 16-bit index buffer and a fixed-format vertex buffer. +// +// The meshconvert sample tool for DirectXMesh can produce this file type +// http://go.microsoft.com/fwlink/?LinkID=324981 +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#pragma once + + +namespace VBO +{ +#pragma pack(push,1) + + struct header_t + { + uint32_t numVertices; + uint32_t numIndices; + }; + +#pragma pack(pop) + +}; // namespace + +static_assert(sizeof(VBO::header_t) == 8, "VBO header size mismatch"); + diff --git a/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj b/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj index 4465f3a3..4ca465eb 100644 --- a/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj +++ b/Samples/Audio/SimplePlay3DSoundUWP/SimplePlay3DSound.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj b/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj index e10b2f33..5091b2d5 100644 --- a/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj +++ b/Samples/Audio/SimplePlaySoundUWP/SimplePlaySound.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj b/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj index 418406a9..48d529d0 100644 --- a/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj +++ b/Samples/Audio/SimpleWASAPICaptureUWP/SimpleWASAPICaptureUWP.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj b/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj index 85d9faea..5e0bbd20 100644 --- a/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj +++ b/Samples/Audio/SimpleWASAPIPlaySoundUWP/SimpleWASAPIPlaySound.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp index 09fba3df..2897efbc 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.cpp @@ -244,7 +244,7 @@ void XM_CALLCONV Sample::DrawGrid(FXMVECTOR xAxis, FXMVECTOR yAxis, FXMVECTOR or for (size_t i = 0; i <= ydivs; i++) { - FLOAT fPercent = float(i) / float(ydivs); + float fPercent = float(i) / float(ydivs); fPercent = (fPercent * 2.0f) - 1.0f; XMVECTOR vScale = XMVectorScale(yAxis, fPercent); vScale = XMVectorAdd(vScale, origin); diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj index 4b094416..da9f1520 100644 --- a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP/DirectXTKSimpleSample.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/Logo.png b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7e704a106b99487be0f1eded426e6c5a2c65a9 GIT binary patch literal 39826 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 YA}aUbQ|(Go1_lNOPgg&ebxsLQ0HMvfUjP6A literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SmallLogo.png b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b09d91991638282fc2426bbfd4a517733ff15a GIT binary patch literal 23704 zcmeAS@N?(olHy`uVBq!ia0y~yV9)_!4kiW$hKbM4hA}WOa29w(7Bet#3xhBt!>lF1cW8{o zJNY}yx7Jp@fBW|L_1}A*&w2jmT;+NG20i7 z76pN4rw^sG9%W$oz+72TSF*wW599iL1}27rt9mLz#~=Q0-W8x0&Y&=n;enFSb8f~7 zK@2DKLQaShO9B!o5w=`bBQ#IRtEgOVQ0fpv@xk=u;inHu)8GL-d2OyGA&U}%`>q;rNr z!GejwSx)#Yvw{!v0)tEYAFPZoXx-t#$Z+8F)U(sQFByyMn0i5~{L_aAj}#vr%Gv0Y zD6T1x#`#2P&h**J!XD3=ea`VPFi8Epc<`Tv{eoFxgkIJgeUzW} zmveGCFTN1i1-2YCwBUXIKq#j1b%8irg2cQ-5_{S>SsYJr z2q!99bqFT)-B3EmAwIK@MJdt4WKzQtg_j*7fl5bD6fI#|>6A4w)e&&|Y`o_5!S&Il>B<6_BABTU2kO_OCK%*#Zj56nw^&!NK9-5~si zBd$f@P)^f?3GNX-5zZ@A-zaYp+Qkvh+1z4yNL^|23jZytRYE_HR3uq#oDku*M(v%V zoZ>vyICVbZ_{knBd?zP8@#9idonYk2?V0Uy+e3Fr@DjUA0-1As)Lu`>J$dg5$EJog z3ezWUpTIxCf70)hho5X0u{zrE$cJ;0O3;!iLSCk+_D@-s&Np(JxnNb`*_HFIaIEUE znjhtvyPzyUKe&CRuu17G)w8q3oKG*&U3~SztjzSx?-}|pOLlSIZI*MLeqs8h>=*1W zpTBJWQqIHM#@l?{BS}LtTe4bmxx{u!{h2tE^cnm!@Bn zPCO+v)oNR#U%W5=Z_}@2-c4<-ZVTEx7KbEnKPK6$D0a*!^<#w7wW2WQ*E-oVe3PO# z{e0t7#`;^jOuyPE*tvLB+M2Y9X>*?yo@L}aw(-FS%bRn&&MBVbJy)&EtZT2k@mki} zw6%3>&2LrR+IK7IZP8n?x36!#FD;nsFjr^pSF2pB@1>l(%ytFtYTb3a^!zKk%gL`R zUvhpu^_B1C-HYyDbH6P9D*o#Iwf7h0%?(UA%qB?Y7+NHMI5Q#nMfQx$9Tz{eJX|4o zI%C(wBN>Y?dM;Mqq4usl{jq6eX%5eSF%jX*H)=r}<9% zzGg<4U07w<*RbnrJg>#P)_I+KEj%YcI(#dSD)nyHrLC90E}p%6_MNpibFbVz zV|%oA^>1Ij+0rLt58J+X{PN*@#G}G9kLNC*z5LMU3D5Q8%Hks9e(#m@-#kZc-Zg{V z6St2E}$HucxJm&|s@?3m_P&2QhgY@gD7+kMJ)*Xm~0vHzL(+xpk(zx_Y< zKdk&D_R)_uf$<>YQ^viGQjMFLvzg^tX0j}0H)ZW*-OZ-YV<+mw!^s;dUo<)YfcPir zpUK8|(sgEC6g|Z;S2Rlcm%$k|AGvFSeQoDC?hDlAFZ=29^2|1ljtA~J9XsSRC1;BN ztQFDJGFqkgDsW41Nny!%ooj2JME*|S+xM}5WzSCQ+gaO+%F@?lRL{jGiA==Al}SrTePnmY}eTC zpQf!nnfFQMv)ohCliN>yf1>=e`15VioK~NUi?;-=3*Zy;(O;om5iJp2vBP7pN7NPL z`)U7P{Z!^|606xeVMD-<4V!Q5sEGXdKxx10ZZYNVVDWN2!`Pr*DHWL?F4dmSIK64w z-+)IEL7|_rD(`&i3u?Z!bg8p;Q@F|0l~Ych&Rh2-YG<-&;?$JT_gT}gMu*jFiBFAR zQ?O>mx*r?dc079&?iYWx=4)l{ty}lJwx4?Y+T-<-*LiEcNA6$mwKvQ0>V>usylbUD z_CA%4&-J=jval-aYv0)|XHT7FHcd2r8+~Tmn%kcinl1iTHMc(YblBgutGDmFsdnqy z{=4PXpZS_)MXm3>pYmqUR_%)L?7gnFU-K@#Yr5Mnl_b4u|FgQgJKW3tkIw6_URurm z&Gr53tdjhkJL~uF-^7_4WY#O^VO8*Sc0>NH*>7i+Z!L(@;ydK{^q~6vWi{20170jV zclgfXv-fA#Z~w~i+M`nYlGXmwHM)y)7uYV``~F4G;<>VMvhMq~|F3&*_&B-rxM_d* zyajVLY(M^d(lq(;@|5NC=K9&&UYU8P^1IKUnc1;{v3t{<&(E_LFL~#)J^uU2&-b49 z$9~vT@I~o+(rwl4-fL~w*}B&i{C()LK05z(>i5%c!)?};eDQs4eewO}`d?WGt`=Ya zaa}KVe&ycx$KFV9&r`cAvqN>)*B@oy-inuVz4N&fTh(8&{?EQ!e_yfx;(t}Y<=@8C z1Gx`=BpgUMe>jr=Js)TLynj>vUv7VR$^DG`Rb@Bj-u}7r^3uFgdq1U|oBVM3rscxt zPt}F}uY6s+`uY98kA8cfkN9)r1NYDF^ZVCTuKZl|e)Y=rR>zf(%kMc?Y5Q^6pS9<1 z*S_EJe%Jlud*x?p{Bigf@cH7e_D2ed( zu}aR*)k{ptPfFFR$Sq(10UP^@g2d$P)DnfH)bz|eTc!8A_bVx6rr0WloBA5~7C5J7 zWO`H;r3P2|g(O#HCtIc{+1qj1R9IEy7UZUuBq~(o=HwMyRoE(l&9%xawgL(3D=C1L zlw{i~If5)yi0}h<*DQUJ!86_nJR{Hwo<>h+i#(Mch>H3D2mX`Vk zM*2oZx6$OES}N1RzKTr?%9JOdQ%kG7xRxGzE!j8*mg``4?rT zXXYj5xa237g8b#_Vpow{pqG-FVr5`rZfIm`Y^rORY?P*JY+{nAYmsD_qMK}DmYQOk zYH4I*Zf2v8(-=gmf?9=S1tia;RMQ&nCcoQrKOmsr6eUAn55e1V`xXX36!rP z(kY18!ydFrX2}Lg7A6+D2BxOT(4b9BNzzS8GBh!_FgG_zO-q5kGK)*{iz<;MKmh_O*n(3FQAJ@AIhjPp8a(b?%Sx;glR-tMU2$Sr zDmajk#1Kw~=m1$%Tmn*nCBoATOcKpglT&q5j8hDC&5}(_brX#ZEOgD1&CQHV(oB+* z(u_cnfTkU{9pxFRd3K;WMAyJn*T_7?(9Fuv+{)BY*TCG$zyM|xSQTzViu2P-$`gxH z9n(|uO6(w&7Gf~Q*%?$xnJ8$4XXd5kmltcoOhwg(+xX;+#Ju#>6gz#GMwkG)78`v~ z)a7K-Am)O-xVKFUU(*D9KkyEGWpyOilzP z3jMOY6lmQDFUMdWMKXhqeocX78JHuWX&2oAh;)kNN_a3S3^6}boHI=vn(q=gr|u*`>4TA`;c8rC1wD^rJ#pDE6n#wI3a zmMJNgx``=irn+VZCT6;p=1EDqDalDjMybXrM#dJ2uxKT2^cGBma_HPAJ%pl&;L;L21;>4Vzwfc0W9J1U?av6XXCYGO%# zQAmD%4vuCwigzk<3sAHm%0Gl@sV<2nsqh|wp>c?zF{npiXaK9d;D$g{qM6~FpOTqY zi7*3uY=O)`Qi*OxYDr>BVo4%VrXZ_DGAAY3DlNY#H?hPHsRBR31ije>FgW;nQFEx4sv%=@N{)HGqf}_(>2mFL^cLV9aeK-!x4^o$*G`T zX)$Uq20V=Cl$eex3TlKy`#jit?FPmcNy&+6Cc4IkX2y_SyM=k0g>Gt+fkCpNfnl1N zc@iYy;qErs;V?QeF*!9U$(RO48>U$p7#LcZ>slC@8A4s1l4_!xWMG_>Y?^3no@Qo1 zrmKk?#(;(?BBDTLBy=n_Clg12Bqf>|8>OZgfC9t_>S`*5b+WmsVOoj>EsRb{GB&kL zF;Am`t5c1WjV;ZRY2oTL!$iYWBSUcFqjFfMStceWB^jC0AVAVAlMT(yQjVV9O z)SL*H%-qzx;>`R!I};NdeXt&M39K3;acM-7fNF$98q%BzxbTLE2D!M|aoOmDr+Prs zK42+GDMLdN>M$DGprD{IY6(fTqK16Ns32P*JyB&6apkE9!*`N!9`LCkfeAtb&UoWNg+Uz;?dMK z8eAlW07;7RrY*?PBk=1Eb_wg#Eg zmM0qWPPI2mFo|?GK4!4;ycoFrhunX`gMvMOSWg%7F{K>+c+#`NXi9TQ0mE|vP9u>{ zmoG=39-nmQ?#w#7l5k)CmnjGPXWpB+?)v(;&~Vdpb1apW7+f@%I`=CvbsRbP<)XBM zOUo6;>JF!Bo7mv>s(UB^A;d>xQQ)OaJhmVBda@IwcUG7rd*he1h{x$nA1RGkUFFuo z$`U5GYNd-Nl7(9`vn+2p_a1zsB`KgRamj5$tn*tA*O(esCZi=AU##NbU{X7B>BrI6 zx0D4;-t`wWs2u!%x;;COF{p)Qj>_8!XP$TdS2VGRQ@!YLvXxV?aGk8|P8SZY%acw1 zq?q_J1g?9w`^g-W;7|SHj4^I*%Ex5_K4%**`_RJ`67C_^>o-+E>Bx?6ZbHYb7a8a} zyirSMzWFQnr~tROtQyP2+}_3~ECEb2lKee{y_lX(JpLll%!q3NcQ~iCFjxO9$494A zdfWp#T(nRA&|R#2x!G>IO3~*NM#~K+FP~v^s^Z1&oQ7H68A;tIRpJC2%+;50hdNsq zAA05{_s;71!;m?wYMKQ~jtwfwi}`#W?6Gj^o@OFj^4MW>zsYYG>u8y$3bVw#dUy*B zT^1XeZkEz#5x6_iCb27k{lFEG^kCr&77j676O0oM17a1#6+4HA1q;{92^k)Fo%&AY z+fK~!UwE;l<0JU7x@Y~|#M4Xk)vk3C5=Ub!_@4`DFPwKZbj522Czf-f zu7U@JvuvL7I^MCq;5WUXpddQ>cIk@e&!0cv75n_onptmqzkmPstxa7_=FYPWlk4xl z|1Lh)IOS!@rp=pmn;v#P%qTWloz{GC!Tr~aGtQ+|KmM3eTwGTdP*z>`}z5~{+~yO{`@&`kh7)n_iuLp`F4LlKQHGB|MTtd_vvEOty0sCW{Rw1 z2ngL={r!D?+3#=X@7Mi)^y=utKTI-C9Hp{pmtSU>>?(bIZE?Q5taVw;CAn)ko9s^c zmo_fa`1bw#_3PK~@BDG@QRh+re?L4!Ll>?)y(uO#a%b7wTju|NJ-hAR&-HxYzvtJb zrKQ8y#Z>-y@bGW-_qsoq=b!odyL3hU*LS$vsi=H}tkR9#*P z)C5{Qf3@pfg}n^l>s{+sttwb||GmDxzP_Gb+pNbQ^SCOXKQOSgxN+~ErNxc?H9tRn zey;!S-rx2Ek9su&W~_QEGDSd=ubp4+PxagP^}k;%wzv6r{_*|#9}iDHO=XwyQMkA z(T}hB_-uB%S3Db=vQze%oZUQ%C8yu53|_yt>T6bgetv3dYGR@z%jT@GX-~Vw^~=hR zyB=pQI4A1*@y*T8ckjl&w^b;(^!D4oUr(ot>%~;O-y6@ofF)?z<(Ic^-Kw8&TmSc~ ze3yln!|rFtqx1jr6wFde(r{=vw94whr?53=W^9_Ic2t1rvVp?lvw@+Z%?B6gcr$Fi znPVgO{@oiHd7fQ&<3htf*0QlJWKnFs?z8mwj%Tl5mb{wty2MMDmGNMSm2S<$Zl#tb zZ(pV`J?DBa*))M?PJ9GMsqO5u$EuTqS{6RG_Ez@~l5p~Pnvr29?sZ1EQgW?h%(T>+ zb6LECFUxj|+@7U5#V_($>(VIecXQ5_TFL6q>+x1=720C6^`FiXue(pT=1BL8hJ+QU z=~OYEbmtV@u=VLpHkKz>JFit0&gf9+m=?R&{a)6S*hu5HFzuox+nmZ~i_5gjm9MPw zy)EB&#nZC3a4T=|#>ZQnbSXU)o%Ia>vpxMu6^tCWA+c=+F>W$I^hHhevH zvDH+9rE;cIaN2FT&qkVJDmi^BMSHH;x9^>B^Xd17FJbKw$0HPfcQNz~>(u^?CPc3+m^67#bG414_!e!JLX`tz0Mt3scwqqEOVKeO!m zoO9cpDkJP}a)zZGiele#C%tfDRP^PgZ|k}gCtfmnV!|lB&*n>1yJ-h|`ZafT_G8NG zYUSF-Czvm|%nUmxGjX9Iqp|g+;QSP>kIPtWTa!0eS+BG{61a}jtZG@xmL-kTtdl;< zfB$~R){bjEr=xB1;&0g#Dt1h`lsv88NzGBX+0o#;ru7+-n+Zyu`cdhb;@S(m46R>p zR@*jrrp`N^b-L3H{j+)FFL{-mVmaD(IpN)vY10L!&k~#X{(gwj_JGD&X0vyPxokeE zq~tXJocANATgUxB{xM8ZkDVxQ+u(I4atG^K;e$#_jJ#}90!7a_$Ly14xV@_;z3$LT QcF+-zp00i_>zopr0N0Pd_W%F@ literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SplashScreen.png b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c352b156fd090a57aec7da81b3b19a3fb5888b43 GIT binary patch literal 26474 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 omdKI;Vst01?W$S^xk5 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/StoreLogo.png b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..315472e10b9d380e509b2f041ea9ace5f994f5d2 GIT binary patch literal 24268 zcmeAS@N?(olHy`uVBq!ia0y~yU@!t<4kiW$hKaHA&lngOI14-?iy0WWg+Z8+Vb&Z8 z1_mzQOlRkSfQa5QtnPFo_|tML@{mXln;on24z09FNc=O;@=*=5{<0XHb~P@IXoEIXB~k zAchlqAtyu_PDn6p2;Q8+#W00|A*Zs&Nr_<Sfx)Hy4_3w(wC?a=WH@ko>e=bumyAVrOuZmg{^`SmM~aUQk>|0Og9H@K8$kfdjajA^Kq3*M8j}-Sr27z=Fqss3L43qc&?03*+ zWH>v0$zukFJuf6;R!kB1ImW@j;Ig1mYl9;@&q0wj2l(b3l-+YcoGFpb#eqlVfQ^6? z+mi+vu7wiQ93?{zSlwXRx`A10f#9r%0$UCmTJS!9AQaR1x!JKfw@AdYH^$-D zgxe<+jJp1G?Qu7p(zq#*`3h61!_F1*QeDRu6kjYc;g4;YwkZ3e)D}70hHZl1h5r`SDxsf8Dw3==PKa<@qxMcw zPH~=UoI0Oy{A3RmzLS%l_;D$!PB8N1_RRLU?V-CQc!}L5fy_BRYOg2cp1k*jV^hN# zh3ONwPvD>6Kk4_$!%w!0SRL(ne<<1&Zn2?F1~tUR%UwU_YD1)CA&E9Hp{tAzcBq$_6zox z&tEowDd*vB<840fk)$D+EmBtF06K$Tj=J1$16Fnh^@Z5QZ{t=O0#w6 zg35#X1I`D=FWwjbx9L|h@20j^w*_q;i$jvPACv4=6gy^=`Z2=kT2UDDYn|*FzDd!W ze!lT3WBn~%reEz7>|DGmZB5$5w7Jg;&oc5I+xXyv<;^)>=M>NJo~zbn*0tB&cr9yf z+Sc3u zFFC)S`pWn6?nU>nxnCB46@T^q+WU+0<_0DlW)mcH3@wsBoSBgPB6~*Wj*A~!9%7jr7M>Fz9X^|9w$<#@+g7Zdz4l1i?A-ezk3{-4FKK=a z&bwv!=Fc0hH?!Wby|w(7_)Ya&?zi)@XJmwAuUVH^*A$hMo+-;I*zpg7th{3`_9^%xmWI< zu{~P5`nRv%Z0VD+hi%_Ge);e{;!)w5$8(p@UViBFgy;HkWpR;lzxT@dZ=Rzz@0vmG ziQ7k_AM8C{onU2WoBHeAOJ=)cc1-iD=C|)#womE4?LOtYYjrd0*#FG?ZT;)?-~J!_ zA69-6`{>7-z<7}HDdXNosm9IB+061RGg+3ho3i$@?q<{Hu@iOT;pB~!FPfZxK>U;R z&t&5}={mD6ik{+_D;g#J%ixTfkK8rEzP9rm_XX7Ajvexuk~77B z){1Cq8LiTL6}Tn1q_E_>&b2j9B7djv?fcljvS+9D?W}D@W$A0Oa)NS_-^||8uw&JZ z#)|eIt{%^S-~klU&8F=I~uAnnSDl9P5SfA$S?xpr^O`J06|buFjNnKEZ_5O3zRE!x)&wrgzn zPt(?(%=@JBS?($6$?d1UKT-Z!{Q0(MPOHzw#an{b1@MXa=&#VOh?a=1*x|9)BkGFr z{j`6tekyY}iPh|#upwZ_hRrv2R78G!ptRq0x0rHwuz0ziVQkQ@l#0v`mugREoZd9; zZ@{C7pwLfQm3Kb%1vOt_Dcof0$|)yL=dJq^wKG{XacWBF`>g3#qr>X8#HYru zDOj^&-H#1!JDxoX_lv(;^R+Vf)~$P9+fTiH?eTia>%2AJBloZO+MDHg^+MYR-nG&n zd!I_j=X%{MSy+|zweRefv!~87nuyCMJ9?6I1=X=ll zV?XRE_@eYZ>9*>2@3pq;Y~AY${yy|rAD#a?_510!;Wq0^zWBbjzWDxf{jaP8SBtOz zxULsFzjE*UV{fFl=c(P5*`d1Y>yNT;Z^g^G-uc{#t?I8>|7YK=zpvPT@xQ9y@^546 zf!qf_5)LGsKOD*bo{zJA-oGjTFSkFuR498#6F?c4me|ltlRY zSS9D@>LsS+C#C9DKU4vo12*HC>R+Sn(7-E>l+*B8W~%e z7+9GYDL{de9hZWFf=y9MnpKdC8`Qd@lr&qVjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(y-J+B<-Qvo;lEez#ykcdDAuw}XQj3#|G7CyF^Yauy<|ZcPmzLNnDS<44+NuDx zs3Nz(*B5S8UNJQElJj%*D-sLz4fPE4b942v=`1b@N<}yltIpz(%7Rq=pw#00(xT+l zpwu*F>;}1(mEd;*szI)0sd*(>jjG5kz;6&X`%{wPdJ0O5a=-zdlB}PalbV~FS5mBR zsAq^Z0199o8MtN8HhG;nu0{N4LFLe{EITv zGxHL2T=J7kLH_b|v8%`}&`Zfou`)0*H#9OeHq|vuHcHbqHZe)mwMa5d(M>inOHDCN zwKOs@H?z^lX$&G&L9Ifv0+MG^@{==Dtl$A+m6&2-U}RyGrfZR6ZlP;vm};tYGiC-VVG!;1hWvyFbs=4^NLFn^O94ce#y*Cu}U;CGfhr3G}lcuGc?vUN-;6i zO-f2N)-_8pHAuEJGE6c?_ytKjhS4smMVV!(DQ-pix!^2RkXTfl3QEqlO0e_{&vVdl z24@JXOiVXfq$V3!nwuKxCMTz*=^7fE80uPBq?qa&C#9vBr==t%8Vf#u_~CT+2$V5|cqird@Gj zSt>Y?ki-y9hUfrUR9pg5fF;7y3``QuQrclFiMGOwvq} zlhTYpk$|Qhw;kmfsd;vwIz-pNRM*Hn#L&#j(A>(@P}jiR%D@0-6j&8*LyGg$O3D+9 zQXSJ%^GfU>l@?+!#@QKENtq~UglFcZNGvGG$xKcJ zB?|qrycB5N2rtKA9z`;Pj($ynWEq$vplKJ~0f=;pwxD{MYC6)(R072)sHBA#yRgiMR9c~@EgIGz)GJemj-M&cnZ_n2 zW|k=_mb!^4X{Nen1}0{@mgY%Gx+%#?MnPZWNa=&x@qqPWFgq%s9~Ak0GVpGD-LpZQt)(jHZ!y|Gt)KFGekB9NgY;mV8aoPdC94u zUTHCEF9tk}=aiU^Dhg_ZL;F0~d+i3s7D>s8X(qbHhGxc)Ub}^PnuTs^l7T_8p@CtV znRyZ<;o|yIsbN}*1ucwDNisII zOfgTRfvZ!ElZ`FSl4;@UG{Z#0R3k%h;-hj{r&%T@B_$b|(jY+6ERzk*%~F#<>DmCA zLWoP(kkpQv|B*`X(Gqlmi5JRMOi24Z7Xk<<)Xo$kj+{nPd zz(C&+L_)P9OQUOz#IF@u8eJskeHkb@*27jy6S+; ziqxD4m(1MMyyDFKJUdeZ8-1`IbP22)BXMa&l7MQ2L>khZ3Apfvhz7a1*>TzEgQt2x z(>`D+NGU@@66!D-+MuAIFlq@&;X4{!qrpW|2#}TqK16Ns32P*JyB&6apkE9!*`N!9`LCkfeAt zb&UoWNg+Uz;?dMK8eAlW07;5RQ`cy4krV5(GJ&B@tb(d}}i=}&(H=OpEAf+u#fY+G}3QqBY>vDph$DjFvUcz$4E^-(dd zI3`!!HuL4XRppy@ykC85N$Sq(U2#`;zrRy_{%^)S+iEcePX`7@0Tu=hm4y4u9rBzV z4IT^=KD8bU;=C%)pc)po05F{@*?wERu0DkCZem%DZu8NZlPxdcyklN>Fc34n^ zwbE@Kzr@r`|8sA{ob+dBgh?`Tag}Z25L%*TAqx}FIKtA%H0e3^%%UT_%G!i4jtI;zYQ7rp4-9#PV9rY5auhO;Y6SlG>FK|=A& zr&aeIEt7Yupe$_UW^Nv zpY#ML7DNYDZaB7j!kQPq4lLhluw+KCAG?pvWFz~fr|K+rB}ip|-*Kc=vwMR2rgiBv zmAWzlXI3Y0)w>vKP2?BgVtRR||CsV*b$6DN7deGoEnPYL?Y1p(O?&ydByj$Wr<*<{ zwNCD771LR=T19D*p%Sa>R*_(%>49fO850U;E)vjY6moI0TOEALHqtP_VD*{gi#p3* zX#QE)Fh`1)eY(YZj=d8$I~>y7wQI%R`S&NUxO(?n$fEgKiN2dAimA8w2+S1a?lCgp z5L~7rl9TVM;k?AgczfhY=TF&}*n*wImvr}B$qQ|5+zw4~#ev7@|evj|< zoX_|A_vGKcR&74}+_K9r*S!9<&-|mBrIe+8)~!PC=V_B)rWnmE-7N6yLN|--TxrvL z+jFCZs(Uz6e|~&sX%rrzs;Jenb?es4%l+4{StBFauPQ4icW>|R&u_Qi_gj8hfayT+ za=*D2g-L~(E8kl^kGcM}{QbR~ckaxQk?T5VInVO*!Xo zRzACyL;1PNGgX)T?zJo`}S??h5p;hvG+?iXI}1O-1GI??D@6dZa$r^Ki|53-}~R|UZ-8w z^stxe?U%WE>(;KSudm8y&-Om;EwuWd%B0K6r)m~%EnfWcOTq7R*B1BNR#jB|I3}Gh zBO_CCw9v00s4~((L~U|9^db?R$BSUG1+23IDsL&F%jGk#|4#_<8-$Kj-JyemnQ=+uyr) z*RH)iJ$_%!`+Ix0-><7Svdo#aY+Y_o^vri3&su(~-Cw`q{+72DHs9`Xb8#IDxL;u| z<+*6Xu5E0IRmZ%Bzc%K9BF>p}9$#GSety1n{pZ)SmF#{#nY{n+*Y|xD-!AFTtNFBi zfBk3v_}Z`Y+v~p+Sj%a*=p0tFn^(Hum4RcSeE;osxv2QKsJN(@sOZ?Q_so5n3$FQk zu3NXx%vX5H6sMw~1G{4}!_+pCD-j7Fn)AizNe!X12d~@XW(mt8qn#*SK zbw8JW|M%nL<7;1(%(Z-G6+S$4o@4qFEjOiuH`n|=ncS}{6T4&M#)ls6>`ERg=jK|M z|G)Qlef~X}{^J5pFWk?~t$x(G_V)JuKi`|@-i|tZp}h9R;a?|(U%!6sF5dSm?Mmt2 z@Au#5=ic2{`Z|mw@rj$GA}@o}gq6)I9}l&1Z;`uWm?}R>X6MCw_ww$4KOPpYd)4^q zin(*Eb8qYD>VJ)u7j8dv?wsH4ZQb78wbyU!G0yN^Hu>d}*J-ixP8?y`*3WA$Z}C-j zoZz(KkhVu!Qb3Q(kva#xg{-Z0g@qFf`4$D$3arjP&d_3aWRpA7#$CI#G`}di3#;1a z)m-M7)Wo9U;StR((iGGrwWQYke(Y4Qr6E5wBQ9|teV)pwJuU0P$&DuSt}HOp+H1w0 z7CCW}Szm0bZFa(|EA74)KV&Zbyq0_Mlu42O^)qIkT^KucX4l>MUeArL-{0`dJUoFn z-K$ymRb{m4eb1xyJ|^}C*Mma$9=Xzcu%i9*=S5XL$1g1oRW`VK*)ibo#0b-qr)r<@ zi%c%m4>zAVM|$biqu>8a=3Hek?A;V}UhQ0?Pomu8gZqMJ$^4t3JFED3^E<{%1|M)eS4*!y!x5^;9mNyU(A~trR!w`ogp))iP~=okFaS_$vE+GhuOc=M3m* zTQz5|o#od9om%?gn{{msWZ52kR(%#{9G=?46L@mb&W)OSK_3gVW|*e9S=~%1%g=Vs zJFXhyk1g6+U-f1odR0#bf$MXX}^0fyf(y*%`$uW-N$Pp=6v^&Tcy4t zD}$|3E9A$tZnJd(u1T8@hSxNjzI0llu8%>QR6NsPvC~UdEAxlQ)qn{# za<5m+JE5)^#2Ym;vDGGR1%K9jCm~73ZIjuGq8~0-n)dZVT*LYPZss*EbvHM-Jv}bu zU7@&c+vTT03R1bM2Fi8^BUZ`uE<7h%+|e|()NYC86yJ`XFEhOl%QKvMVYpdg(Zs1v zo6c!%vX~Mt8=Bg8{i9h?k07Sz+#&t;ucLK6V)2=KrF literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/WideLogo.png b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c70f68e2c59214e0ff54844ccd8ae5e955826e10 GIT binary patch literal 46540 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/seafloor.dds b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Assets/seafloor.dds new file mode 100644 index 0000000000000000000000000000000000000000..fc313c451d513fc5db6b8bb8a73b84235243b69b GIT binary patch literal 262272 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�RBqP}+xJ$hoYbvNDLI_ATvPaIVg@m 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

r1)w+wrD2d5hz98gu|aZR zK6u?MWDhCG9Ee?@IYZF+FJzr4D2;>M1abpNFDMOx$_QA!1_~!oJb>H`qCs|m;v5_X zpmqA7wJP8;1F|+3f%JgF0u(+V ze}d8&SpQbY{1jLmT3>_8Sg<|NaaK^+gWLfMGf+5#;uRF`AiF{K!O|zF`~$@u$Zk-& z2AK(pCy>1$w}aRqw}JSe@BoDu$gdzXKxTvT4#*!MJ3wZG*r5HAptIRQ?PHLcATf|y zkl7$M2!q%l3}VCDDj+r_Tp;~*P<{rv6C@9ECx{J^homo%n?QUJ4RRBxEe-Mq$X-yM z0+oB9wMXFoNt7kHT@M;p1E~Xvf#Mld&x6bbr9V(z3`(yc3@RHy?Ep}pA59jFZj%FCd93u1%J0_9E6dLmHU9;6=RCy@I8#0T{!KxGmr9e~^gss};(L46%iI|vl+pz;P1x7FY>0F>sybyy3e&jB(A z1LaLn+=JMlFapt_JPb@)9Ubfz*QXG02Y~8WdI_F_2lH zbN~t?kUFp(pt(uVy}+RJ9zpGW5Dn_bf%YGQ*5^aVvq5nKQx8j9AoD=+0x}DNLH9^y z{|BW7Q2qtwC$PS2pmO*ec%B7hKPc^j@&YK{LFpINUIvvhAaM`|nFZ1h(hHIYhdJoZ zAkZEr(D@}xA@|vX>;|P#kX}&ygY<%EP@N3&BS;RE20(rXmFJ+e2NDN`6DXg6(h{hA z1c`&}1eIAJGeF@Cibqho0`Wn8K2W{^q22uw~Um!C;aRdqw2IX^P46+C0 zZ;%+MTn42LP+Wu7lY!g}G7scNP`HBZ1la{D4?+C~kolnYHb@NQCvd!g&fWeGxw{vX zpFwFE6eb}5g3JP8kXfKS4yxZlZUw~+D86BN8$^Tb1f?rb842?v$bOJGC_F$kSbQy{ zjs%$xO8+1+P(A{UH-P2`L1iV#K9Kn^4AKiy14>sQ8srWT4T^V=T2LAWsR5-aQ2c?y z1C%a7@dZkgpm7;coPx?tkUS`jgTz7Rfx-q9_Mq_zP&)uL_6ITxluto^0i`ui+69%% zpfCfO1JVz&8_C13 zyJPDV@Yo8-Y>+r8?m%$@vIA6Zfx-o(7nJuw1epVJBPiTJW`Xp9!V5Ge0tzb-2B`zN2b9)8ZUp;x3Ur@9w%319*n-o3aS(XC z5M&o9--6maptuF;2Vsy~K=lhaFM->{d%}>>@2{Hqe ze?a3gpl|?{i=glWr3;YVptu6%15n-orDafDfXa4|K2X?z(iBJ@ly*UBtfe{#yjB5} z-$8i|p!5i; zPeAgZZ~^%hG=Bst8$j*?nGJF)C|`p7400Dp9Y`-I&x6KCK9%Y zbwF&8ILJMqGz?;cNaSfeA z2blxPUm*8^G4z}lPV$UIWe1ZH2awo_ypl|?T zkolmr3Ca^7`$7H(m3<)pgY1RX?I3eN7*w`_?^)UlI+tlF_%2|OIiR=$#SO@8ki8%` zf$|0@ZGioAZ7+CE9GnJ_#w9>$8<&tl=eaK2+BiX`<6n^#s`@P3QJI2g6bbo zT@5lH6y~6^1mp*hy;#z!!XWcNdO>VZ zT!HKW?@FP`U!S5u_HB_Ce-?)PcedRR4hD2$o(zdO_xZ^n$_;WG<+DfXIXV13J&}7&r}r z)Pc+cnFUf0@;^uq$c>=%53&c;7XY;>z-mEf4}jX);C3x!4H8H{$R8jK@&_zzK=~Qu zUXa^CVjw#}Vj%NDYC&-c3O`U>f%64)FC?rC0*Qgr639Oww}H|QNDky55FZrJAag)r z0Lrf*w}Qk#aR5pSApM}a3sk>=>JyMUkiS4~0o6C4@)8^_&(DF^4uj-D{s*N=kUmhI z4hmP0pFsA2+zX*0YY;&32~q>PlNogPI>>&IA3^B|q!yHBK;}XCpms21jS$E@kRL$u zApe8>1;U^{Iw&oH+yP40p!for3Gy4r41E#I0BWgpnL;T19BV4 zEKoWF*#q(?NFG#Kl+*@83TM&;5h)7)T#T4=DeE$~#c~4a&cuGy}q*F#%B80+|U)CwsSo&Q_lT-m?QT zALMS39UwJev(7>8=mv!)s9XZ21(5xq_yW-&cY(w}aRb7jb_mGNAUTkKL1Lh~AC!(j z=7Q`1xeb&CKr|@4LH-2U3kf4oow^mg)&!&8|a)Fko}-^1F{>`_63c9foM>BALK_+ zID_&nC@esE5A0viKJa66{)5J^LE}}RvIH{Dy7oV)EeE={9hBZdW`oiKOb^JNpl|_U zP`H571t<d>;#1y$gL3Zmj7V8Kx;|g9|O;6f$RX~V~`!7at>5> zfb@al0Ms@GnGG@z6eggs0jUF}RgnKc`4;47kQ+ha1j?JB{y(Tq56ZKkvLo3^;y^2x+e*w9u$5cdq8%8?x_U%7nFxV=@67hK=~ikUIw`rj9Wls zE}*&79`Jdupfn1~ub^@dq!*kPKx?5u_v%9L4Frv6g5*GM0i|cKouIu_pfeDwL3iFk z)^C9P3Q8LwGePP=WeR944;+8sGcQ1QPw)K?%448(3kp+ET!7pT3O`W30P#V21>`0W z4eB$4%mt-gh&o7{59BvcSb_Zx>KB90?_T>K6h@#j5wr#elr})^D^U6b<#R}$eGk5i z7nGhr`5lz5L3sfbULd!F+zXNe`4{9C5C*vwWIsq9DE)x?6`*her4dm60mUVV4T^t| znIOM|+zu-5K zsNMvX+2F8--aiJ)7ohYH%7dUf4O9<;*r4-vKt0Lp8ivI7*KAT^-$3M$V);Q-3N zAoqjxgY<&fAb*4008$G|!=Q2ktPZqZVoLIV&>53+T7tl30;oIy^({bU254*#qzPBgYrMv4WPB#=Ro_uAZs8&bqUCPP@ID>$W0)>g5ndDXTa_Oje&yB1q0~? z-E{}r9{@gk3vy>2*z9X-!Q(a{Js>+l=7P#`aJ~Yc7u@n6RPTcP0}4-2yo16CROW!} z1%)%HE(F;JiaSu61Eoh$9S7=TK=Li9yo21$3i3P1-JtLTl}jLVKp0dOg3=2p+(G7p z)^CE+1*mNa3M+%mw)!q#qRDp!^OB1CZGu zGeGGUq!ttxpmG3|HbLnfw02HWg5y6ZpMlo#g6cO=c!AV|{0h!FeRv3w(wa zs6PyHA1F>h^EjY7AC#X!ePmER1=W9`{xGP#fUph!gXBQ^1gZu{CzYOv#D11Tb0b~!@ z%w#X{Tnngf2c=t(+d=9;bs0zu6vv?W0f~Y1fWiYL4oeH5GzE%(P#A;q1V|j5m!We* zptK50^B}W9ZUN+8Vjz7WH-pO@XgL9j2ap>;c^!m7`3dAd za9I3*{~uI_f&2g}H$hU^n%JTP?`bx5xLy}3Qv$( zpfm%r3zTj^c@pFXP+9=l0dgm(Z3|jM2&z{=VFB_RDEvX;0COuSyg__Wz66PZ)PUR$ zG7n@9C|*Dql>R|s36ckw3!ru9uscrff#w@QYr7%sD^MB&l_?-Ufcykbr=W9r-k$@H zVSvm9iG$RD!WHCJP+A4K9TX3s@CAiCD851c9?%*DQ22q?Mu5@?NIxiVfZAsub3pzE zjj4d*n7XlKPZksc7p5%ogV^9n;!5b!U|OGgTfG$cR+F= zcYxvooKXPE!-B*?;RR9)%I6?CP@NA7YmgbBFayO8NDkx< zP`rV{2ILkP4YCvD4v>35=>gQ|0)-nW?SbM1Y$kaA0dyV^=&rsw;B{!AGzr3>Z~^6E zkeQ&c0_g>ns~|st+5{jBVuR8*D8GQh29yUuZU*HukQpF(5FZropt2D}gWL+rpCJE% z!Uj}!fXY=+*nz?V6gHrA2TCiTbOhpq)PiV`UqSu?VNm>n%mRnwxxN2EYC&xXP#A&I zJ*ce<(g!N%2Z@3DI$*V+am&4+dmgj@ zgW6r7ei>-~5ado!n1j@V;t>>Yp!qaVn1b4iAa$TH2ZbLf+(2uyH5CQGX&96zKw%8> z2Pn)z`4g1yLHmP1bu~Eug7*8#$Fer_HFvyJ{H-Tsn2Bis*c_12;Rzc|)l)gc62+D(?avxOpfzlbMt^=iA5C+MC z!WJ|J24aKcLE!`nN02&D+6K`ezk>V;iYJi0Aa{fECdf_@AC&h&;Rz}qL16|;N1(DF z_@@B^s_#XTq;gW3e3d<;q>pzr~O11PP4+zG-U z_k-LEqCw#g3Lj8;2vQ5m`ye)`4g!T2$nT)=0p$UZ9iXrS*#pX#AUROG4Wu6=2ckjY z3DOT@gVH$251=pysRiXZPzg4_Zsmq2o$Fa)JVP#l5W0*X738$fXiiaU^cP#y-=YaoAv!VrW(;RuRD zP`?LM7J%Fj3TIH>0OfB`xdw74$lU5|OYnL7puPpD{sgtRLFz!^1M(**OhNezT=s#_ zP=KuI1;-zB?+VC0AUz=WfcyyZE6DwzFa^a8C_X@Ag&=pq+zIk8D6T<%1o;^h$Dq0% zR91le07{1-c~Dq_XpkMCvI1lW$eo}x3-UL}U!Zge3VV<~Pv3au+CmKxGA3-%`*RE97iCP(1;17s!5)`JnU$VuQj4xJ_Oh2 zmYU!*ut8-2sQ(0VA1J+n;s+E5AiZF9h7$il`{_Vw8&pq&>;Rbqaz7|MKU$}zJ z9MF6pXgwxqtsQ6{8(I#7@(@T5$ZU|gpu7*t7a%^UTmtzOl*T~r1Brp$4RQl0|AW|| zwbP*T9u(&we}VEpD7}C%sO|u@A3zvn4ya!UD)&J4fcyvwI}jgaA1FV9*4%=^4OB;g z!WmT0g5n_K`# z;RM2<^bb-8N-v=J0);8KPEK}$kKuvRI4F)laRtf?pt=}j2PkYo+!ZWjLrz0_A@J4hC@FA5;c_;veJ|P&xs{Hz<5Te2^Yc zeFh2#h&W_j8^~;spFrk=Xpr3?^`JTxl-@vWP&k162I^me><8HkN;{x10gZ2h%mbwd zkbgk)nxHfU%KxDDJt#atYCz+1AoD@_6qE)*dO&Uj)hQtJKz4!51f?lZx&_IB`~oWP zK=l?VPC@NbP}se{2D%fy1w57t3NujHg4_$r3!tY(km$cg3=7A>;U->6ow%4K>9&^P`U@XA0!WQFDQ?I^nm;T zO6#ETfaK-9|3P&gC{2UH5o9JP{lM}T$UIQ|gUkk*1#&m2t^&CU6fPh)g5m(=K9Cql zJ&1<62b6w57!)5Mx5LseC@w%@2`Ya;=?tU~5@&(9WpmYKXKadzGt$@NAfWihM4!WBhbl(7IPHydg zP#y-U1;^+6W8nRRpfU=SPC;#4P}%{76{v0m<$q9l0CEqg`~#^2g(s*@0BQ?>+zyfh zl?C9k1iDTG#0R+p;a z2+|9RcgUE%*MCr-8WfhGvK5pbL1uv55Aq{OAINQ>@BoDoC_RJ15#)YQn;zsoP?`kI z!GqL+`~dPlC{96j2q<1aG$^gZ+zWC)s2l+0Ls0mF!VhF0hz+w3WERLzptKJPR}dQ{ z29byCUjVT|?O@QE2Ov3+TR>$bD4alcf#MZpF327b2DJx3WevzYQ2qq@0hC8Te2|+# zegnAyl&?TESkGGMo{Xi{|3UQ}DE)xia3FVq)PURoiZc)!ghA$l!)h;Rz3W==oFGUX zWCtkRK;a|GYsa?!2e}I*267iD{y_c% z=>dg5C`>^#2!qssFlg)!6lb715R?Z%ZDtS#ZK=y#@XHYr- z=>@qHG@k;RR{-U2(6|#wFDUPT=5s)P2e}JWe}eRb%m?L3P?-bP586xk9JC+l-hWWu z1*rk0E07$>9FX5Y=7PjQ?gE7khz8|ph`S+oYk|xKl}8{sP+9_&m0)?${y@+=)@#SW z;Rq53g&!y`LE#H(7lZ5rxfdh{N|zwJLGcE%ALM>ee1YUaZ4{8dLFz&A0HQ(VCCGoU z@(vV_pfm+a=O8vHen1!`2BJan28$C={D8t3l+Qr*H>j=$g&8O57GxR7nGkt?g6D?P&|Ul4G@O4vq5%&(hNuq z*pA{LaQOx*FF|<*lvY6HDJY+U+Rz{~LE#4qZ&2C*r8Q8Pf#M1jCZMre}Kw8&^SNHe2{vO+d%OE%FiHwfWxvU z89aXnN_!x4L1u!=3XmT_{)E{H5(mW_s7?dreJ3YFa9aSBS3zzA^}|4Op`fuWus+aw zZRq`_VE2LgDxi50=p7Oue}e1)nGY&6KyCrWDToge2bl@73*>H4+5p)NN=qONN=KkD z0_8(cxPj^r&>Ad|9#A?5)pMY<4jTUk=xDGu$9{MSg{ z38WVk_8_-`^nk|WKxqJ!-$8B%=>?ew%0D2pKz;^cPEtG83I|YL0$~^*BoFHMgZu)*Ab*1}D9%7~pt*2Reg=gzC|`oY5hM;W z6EvOxN+TfiKp2##L25y93MyYfW4|E3g6@w4`3HnS`3__bs0;wb4al9Kd<^kp3;4cG zP`rZj3@E-qWf>@b!F_CSx{rd_OCY;IX$ItXP*{WF5|lqd=^Z2nG8^O;kb6O80H}=s zYAb-k4x|^9pF!yeWCjR>(h!ISg&`>a!{QATSD^A3RJMTp2%b0B>ncY@*#qz+WJgTe&V zZULn|kiS84Aax)pgIwh20(rWg)gYg1J%i(umR;~ko_Qkg5wg@M+WVg+dJn! zNDrv32+{*eOQ1Lg;<9D~dSg#joJgUkixbC7)?w}H|c$UYDoqz_~#2!rx9C=G$^0;N09 z*Z`Ofnv44X9y~t_DnCGF49K6LbOz#s!WCpDr2Yq;gAZ!kL(WYA#~<`8K~SCn#W~20 zAR1f`UfT;EcLs$A$St6B0t#mk8_(K<0q-fa)tyxdKWnAax-1pm+kYK{P1- zKxtA!f&<+D2c=C=x&@gJieFIs6~qUb2`VE%?RF6VJLnFP_t(JpPlD14D11Qnf%CtU zB6util$Jr}7%B?<2jyE(Isv6sQ2GF+6ObE0=>tZC>O@eSfYJ`g&mcC)-Jo~@l`)|D zA7l>5pP)PgQU^-Mp!5n-1Bw$+Jc802D84~sn4mNSas$XOpm+!Q7vyhHT!GRy$R030 zw)Q_Le}e1;`!mS$KPbI`!VeTzpz;iqUqO9$kewj+gTfG$w?S+W2Kg5x1~MOHA1IB3 z>%b|H`vF020=XL$M<9QI_#iuB{s5T)(husdgD@yRfcy%w0~SW0atI^_4wq|?^`W3R z1I0fmy@31zG6&RO2BjB}7|8vgx&jnFpfn9?OM?6Wsv|%cl-@z<6C@9E3&_tPy`a1T z5(A}MkQ$I$Q22rJDyVz|sRgk?Vj%Z{;vW>BATbah6doY^Vg3a96~qRq2g!lb5vU9R z=>v&@`~fl-?Dl(*yTL(aILJJZ8c^Pb`2|FS;vJNqK<))$kQgklfy#GKo&==_P~8F2 z3#zk0|F;HFyg&8QkKxTr%0z`xS0}4NoJSbd17!*dJ zdJr_e0Gf{lg(avQ0f~X~I4J*t>;kzDlutlo2OxKW%mdY-pgaLG7i1U6EugRi@j>AM zN`s&{1&M*o0I30)0b)baHDo*&RA+$P4^jt;Cs2I>5(C8%DDQ&OBuEStmY_NZ6b~SA z5DiL;pfnH4E1)zEiYHK+3n~{tgW?l3KLEm@a010AC|`rZ z3gjnH*nrf5><0CHLE#RH3y@mS+BC48UZA$N6L<|ZXgxm2Oprd1-$3CDDl0kHc^aT{4dj1N*n#{7?k9oHYFi3A*A%i|1r!D#w}J94$p0Yy zApe5G9#U>(gWUpB1F{$7e^7Z0%FiG^ByT5!_j7>E2k8ZsAs}->7-SyEt)OrRr3p|v z0Qnh|H$nPAZ39qvg3JM>FOWPa9fHyX$iJYt0%4F|P?&@A04P6zFsS?hsRN}q5DiiX zavw+>R4#+k3dn4b-5|e!{0DLq$S)xEpnM352ap?KVjzEm^nk(>l$Jmklpa8N98?yA z^nvE?K<8S4@+K&qf$RZ^gT_%o;S8!XKxHT>eSq>YNDkyTQ2GJ69~A!}cYw?U#V1G| zsB8!IBS3sm*nrf7Fer_H>SvH$pgarmBgjrr*nrFhg$qa=l>b5MAbA|Jrw615q#mMn z3iymcklCQ{1<@dVpt1vICx{Qq|DZ4gg$pQef-oq3g6n_Kc^A<2RUkFs_<){U4pIlQ z2NL#>v(-WJpmGN!2P*eKWeTVs1%($V-+|;o?gzyWNDLGQApM}a0~AK!cv;%=ACxyi z?Q>8*1*rq2Jy;xp+FGFe2Fg1ic~Ch3if2$g3d;YWc!Y_8^nv0Ml-5CM6%+@cI~hQF zLHPuvAJoqS$-~km*iAj4^Kn7rPmnPqP<{mY6_k!ac@Sc56nMT83kXdE822N9G{K>cu#J)m+3 z6mFon2I&KZ7btu{=7Q>PQ2K?$=T`6;bB3A{|3Tvd;?P&x#K1&9XaaghBWd60fk7{ba4P?&?_ z5@Z%AU4il)C_RAO4l)OnMnL*OZDEicsP70;3yMdO8c_QJ? z0FC<{TM9Y185C#Wa0l&m-wIm4UyYbkZ^`}-vIk@y$W5U52lbyp`3F?Lf@n~l1ce2t z{sPTcfyxSypFwKDa|7W0c;~?Pd4SY`;u|CfYPW;p926d4GeC2kpmQOiXDER3Gsyp- zbOg%ZF#AAZ2CmORcek!>0iQzvc0cI6Ezlk}&^mnZIY4W{`=LSVL2(L7-ynB^(g`HI zr-0W7g31Vx7$^;Z!Vjbl;jGVf%7IU{DDDfXu27vMbXiN&E7vv_8KS22c z6epmx0LpWqx(SpnL3V=T36vi|W`oxKfoKpP6eplO0xF+DZUE^ArDu>HkU5|<0g6A6 zJSeS$(hEop$Zn9Gpg9FlS_8!!sC@-$pMdIOP`H57B}firHz*H);uVxGK=IepQv4rO zW`WWj$bL}$51MZPxdG%h5C)Z@pl}4mAt($%?g6<4RL+6qLFE@H4nbuAs6Pm@8)P1+ z`~cN~pnMH#r-RG{g%c<*fW$%m0J#a&&jtAfX*f!f`mbOy?^ps)nho1m}**#q|1|9jy1FHpJw`30m7WH+en1BDZ)8~~XQ zVuSnv!l1ANsR5}6*#)X+K;ob@2dYCrX$q7kK;a6i_d)i8!UVE57BsiD6h1xyD*Hj{ z5gZrUmf*Q9kh?+o6_ox#aRRDG!D+K4`#&g7K9%#ltw}80zhR8DBXeF4+>k5dXPOJGeGJux=ERY;X3{(by@(n0Wg4BZYKgbQB_ypx8 zP#l41kQz`tg7PmYeS_44Xpk5ssQ2c_z3gjnHngHns0?H4dGz}_OKyeK68;k~p z3y2Rg8zcs5OM&0!l1YU z`2nO3Bn~ng)D{Dkm!P-;#Sw@G^_@WKL1hdmK0q`mt%LFmD1Uq917%4kUv2A5~L2I?;QA!I?(tKsI3U9FF@%Gptc4mj6iV>>PLXufS~zc zP+tJ#XHXjl6doY6LFos?2Zbjn?}5q(kX}%l0)-LLF)#l zfX`n7nFq2Dq#u-zKye0gHz@o;VFRkiKz##H7=dVz-Jo_FDDFXi2dM+O0i+ic{-8Vo zHWPGa__?*{UVUtKz4%CA4o4KErG%r&I0Ch$Ky4_{9M^xyJuaX$1u_ey7nJ8fbtx$9K=BO9 zf1oqDL2d$#ae&QP+XAkyK>Y}iI#8Je3K!6r0muxHeW1Jw>QjTl7L-3>YCw4(G%qJ0 z!0{iJ=Rox^NFS)~1%)Lj&Ou=d3LB8$KzRgY9;iJFDpO#29OQ10U7$1z!l1khO7oz& z1l47rasXsM$ShF30P-U!9zgy8*#U}IkQgY8LHPz`H>ey1@j>#S@CTU%YBz!00!q`M zum{ykpl|@21FoB(=U+nCeS^l#L1uvF`#|{~N|nl2(k<0 zXAm3I4gtj(C~boB94O8};Q|U{kX}$b5auqBKf!4XdImVS3;^#7fUH9X#Wg5xfZ`35 zHbCV7sGJ757nJTnZ8cE5fy6=nfRq96!RL{J(kiGP2e%uZL-vw@@+ByYAo&q;Un?k| zf&31NKbU@yn?Yj+pmGUDgX8M?IdFdl9FL$qi^zS9=jXudi9q25DjPs)7DR*m1d3k} z4GLe7-5~owc7QM_ErH?-6m}qSSh$1I1;~#eb3kzmk_W{ND7}GbkY11+NI$4d0EG`o zJt+J^_JG7e;RcE)&=@}`4THiCWEaRDP#+#tXM^Gb6wjb^0jeXxaa0Z2j{;h+3zln1 z29Gm<@)Afr$b67`P}qUW0Z@7XnGbS1C~QD+0%C*Q11@twXS>gV^dCX_5L8}(>;k1# z&^RDyoe-$32i5H$vp{YH#WAQp0HqI*8$k6KC`>?U31lxQ96)&yqz>d)kefhZ0>Yql z1Mb@!DuUNxgVN&GwR7Np0Hsw>S^&j4sBQ-Pxg{A~FM-lB*zKV53w%FY4|LyR(0`B{ zK>i202V@V({UASr;vAHgLHQ9Bwjdf5M<92BFvx9Scdl*u4@yVielKVpz;j4@7L+zX z{SeTc4ao1HFawzj3R6(t1Mxv_24P6pwt(-A2D<^YKLm7_=@if%pUL2}H9%nl@&hD% zvcYE}gW?NR#zVv)=Y@dW2Ew3n2P6*4Lm)mVZGiY7cZ2-{8sh=2t%2S}2&(r%WjH8( zf&2w3^Fd`Jhz8BQfx;Ek9tZgoR5pPyNIj_i0MZMNKhV8Y*VclnZ16pnApe5$EXX{N zzd&slP#q0QPawUZbOtJKLFEU?ZLqKb=>x?dsBZ-dCs162Fi0P$Z3OZIDDQyc2vi<{ z$^=k31`-E_J1DL|_JS}dKY{du><5jZf@qLhP?`g&1=YErG69sIL4E@10l5*BmO$d5 z^a^5w%5G5J2ZaNO4a)PNJPI-clx9Hj12P-rS5WwZ;v5w2AU?>gptJ*$2VsyOKz;;a zkUS{8g5nmGEI3Bn-1fH1hu0iB6i z4cP|^ic?T|0&Z_TKL_5Qps6VFpMik^JiiNaBgi~Zdkqwppl|{C6BH((umFV@$PFMh zAp1c628A&wjzDELsEh%PQ-R_LRK|ej20`MWv(VLG?7qogg=W+y)W@^S4d`&+mfM&|1(Q8|XQk z=az!&DNy|c8fONDF{lgxtrZ595ukJf@*61ZKyeMCK^T4NAwL zv;hhmkh?){1(o-RvOgO<9}4mdDBeM4gTfdTZ=kXmM1$N6k^|*4P`H58Lva*%j20vg zD*qtng4RqFgUdxwn1R9ygh6J4)_;QL0zl<9$bF#n3rhE(a0kUXsEh|;kl7&hp!f&* z34}r61#%NC%t7u4nGaG2qCx2l;st(!XWh^J3#J)VNh8Bau*1L!XD%wFb!Gy8P!qX{uZdu2TD62IS>YwSD^3!sR4xv z$Uh+egTf6IE}(n?QUgkppzs2P2Pm(D`ZA!h1>`4?|3GGe{02(1p!x|^W`Ob*D35{K zz@V@J=>vroD6T;61)b3f3R_Sa4YC(hzJV}^569JzybW>-I3A&QiGjif6c?a42k8Zc z4=C?}!W3i%$o-)30@VW`J3xAo{RwhEC~iRU0_vxL+T5VD4hm~fSqmx$K=BN!M?q;H zl(#^63RE|P!Uy8t7Vx+YC`>@{0>Yp$0F4EL!X4x$5C(~Z+8iLeK>9%XL1i>39zbmf zP@aXbLFa3L_U}RNMuwOL+RHHoygm&SM-X?m{0FHAr5BKypn4wUMi2(s3-SjjzCbi6 z4T9VaG7A(pAhjSjfb0d06@bDKWIsp_#0Iq`Kz4x40)-DKt-{zKd5~W~;vgDi4oD1? zRzYGQ3`)PC@BsN6a z6jq?H1EnEQdIIHtP&xqdL25wh8Prx>yL1Y;e+A0>ptJelDEVFU_ukXt~00F|qt z@)cC)g5wQ*&IDwv1{6-9FbBC6GzI`N2h_*}sR!jJkUS{P!1OuDzAccMuzoIR{W&Pl zgTfNzHc-9-(V(ydiGlnBatA1GKz4&@PVtve5ac#cT!6w3WDm%{pmYQh2iXla7d$6*4SZK2NG)hR=dq=bvjjoo zX`uK6mF=MQ$Dr~VUNc!AObC=GzhRghajYC&NG@;{6X%8Q^l0r?l?M^M`rl;%MFGLSw{`T*Gj zN+X~+0;vV1Ymhl03`!Fq^`Nu^$^#&CL1T0v{UCYJID(<30Ch?2kd# z_!kF(=Ltah0_0v$UIEpKpn3`vXAtv){)5sLXzU17#(?TM(6|ezEd?qEK>c*k_#H?s zD8GQzfW|37c@887Dw9BA018J?I{=g>Aobr`@VPsna07)GsJw#BTY|z7ghApUe}mM6 z+yt^09R8qsFv=2qb|t9K1HvG;gW3+DG!H5dLH-2!7vx@${UHB?!UYu8pt=%N-hkL3 z^FjFnlpaCp2~;kE`~y-0YTtt}$nT(Z4a)zZcmnllLE#J<#{!uPiWgA*1FGvm=>+6w zP@I9pL2&}I7vwHbe+(2xpmYFgvw+M1sRg+glpa9-0F^HwcZ13TkUCJjg2t1;X&7`i z)0`IYT24?ngVG(ST>%OwP+9@S6Ud#Q_y&oA;uNG06cY(qhBo7KVkbY1;1LY}@-#{2tE`$02Aag->gZu=FXOJDBxCFTgWEUttKw_Y9 z0ri)_`3-bFG3X9U(0$yXIsapGz~en2H-P*PN+X~=4$5yJ^Few*c@7jOAT}t?fyx1p z`CxU|pnC$5_DO@>3Q`A(OOP3$atx#w6fdAU3pD=+k_V0bgTz60g32gRxd8GHhz98e zl?xymBnDCk!XS5n%1DqKKyHTQ^(o-JS0Fcm;tPa9{s#FUlm|fR02Ke=I0g3;AZ0j6 zJ;=`>^FVO{s$W5A4pcXR)Pw3VkU3y`S|I%ZP&|R;K=B4D??K@X;)CiGP}=}xCn!yU z)Pd3gC~iP%L1_ileg|QY94Nhm%mvkfpnf+f?SRq+DDFXF2J$y3+(2f4Fi0OL?Ss-P z$R8kia3B5oHSjq(pu7vJ13+~dIDLc8Q|KuMr&EwVP?`XxDNq>=Dg!`laGXN-U4zmd z$R1FB1i2R!h9G}|+7&QAfWiV4W}tKlavRA1Aa{Y>1S%^)Wdq3VApM~51gQmuJxm|S zJWxIY*$WCcke@+zg3JfG5u_gC|Fz)t7m&7d6qpSvOJV9jVFqG@^n=_0vJYe)C=Y|e z7L*4-VxYJLs{{2lK;>1k6SzMQax=(YP;%~d$}b>&Aisgq3P>E3_d(?_DDFXhG*BJ{=>>%?I9;4u3LcXM`2ke! zf#Lxq2dWQ1@eXo7C`>?Np!5bRqe1x_TnF|f{|C(tg7PCMoq)ta7?ck|`3@8}pmYaH zD^ZGre8vp``EDg(g#_4b19FN5s=1cevK&!G4NrD0Im zfy!bK289nuKdAl#sR6}5D1Cy|g7_fypfm&8pAV{IK4FDM^^$^{S&}_7F%7 zXnY@(r#Ltm!0jZEn?PX(qG1>mt{`(jG$t)TmcAa}Qd;tdo}ATvPz2DOnu;REt3=)6>r zJHh%v=emD?{~uJJ!s;7PIRI)4f!Y`#|AX8B3U82~Kx|OD1+}R`?gq(&+zt{0b0^4P*w02Ju1V07yN^Z(z5B)?mFq243q2%KM-=2jy2#-Us#F zLGA;wLG?W-zkeu|ax3bqpxXL3V-aD-aFJHz2ow;sc}> zRHlH!7sLjc53(QRFOYvhY>+=e7?gHFVFOD4;5bFP_Yb5WWHu=LKw$$)i=Z?O3TseY zfWi-?24p6P4T>WWA7n11jDXxZ22u;cpt=ww4@!HWv;;C2lrKOuNDO2Ss2sm`?bv_N zIw(*c1I0I}?fL%Pl>eZ!20`Y4(lIC>g3=l&|AF!~sO|!}4HV~~v;-PQ0F?v zZUJFXS^&`yw;O`zPC)XYZ~?g=BnK)pKxH_H4Z@&!2c&Sqs`f z56Y_`w}JG7!U1F^Oh3pipmYW*D?s%nNDnAKLCk}!aR;SiP}qa~1TqIy_JaHj3U`os zAhST}0+dHV=77o(P@01HH5+_hC@BAf>L5@W0OcDH2I&RyL3s`21`r0t5h$EN{sP4f zNFG!kfYJsi9zb~%lo!Eng!SXEf$nSR0gwNI%mt^LV{^c3!$AH4jn{+PK_I=Ld=5(I zAU4PxkXn#EAPlMlK=mMq4JtoDVF=3qAa$T}5!7b^nFZp5)PTwXkUK!?KztAer58{= z0dfaO9uy~_GzUs+pl|~D2Nc(!JOs-7AoZZ|1^F2)HwCf|A0!5fClC#ae~@}m`Ua&B zkU5~Z2Z_TlNIxh%L3s^?LE}ZB{0QnVg4Bb;6=WXB4p15beNLH!cYngGyQ#h~;E zN@E~#a9tDy+8YR(AM^ST88h$#&-H`C3KTvdGeCAh*r58Y8q%f%ox^_&G@iWlKWKad z)HVUR5fo3LasuQ=kRFiRKzvYM0J#HHMuN&BP@VwQ@u2VmiG$n)VuRcSD)&Gb6uuz+ z;Ig3D3%rj4)II~n2gqF@KZ4u_G9MHlAU}cZ0mU20ZV(2Qw;=uCuma!53fc1ysyjew z4U|7X^&3bYghB2GrEge%1-TK_Rsi)CKz;+|N042hbOnlgQ2qzCp}_eO)PC(j><0kl z3y_<@VN(nm`%wh15e20&kQ+hq019VN-Unfj`5<#a;RtdI$nPL|NSdGWAC$j9`5NR# zkQ^u+Kxq=>Pf$7onF$gDrGHR50J#ZN*MsVD5C(~Z@)$@C6mFpK1IdHfpgJ0qmOy0~ zDF1` z0(9Ottd0WR?=S_jmkdv_; zfaVuLc??vifyzWs9syy{92Y3hfiTG3pmm5KcYxv+WH!h=koh1C3ImWGpl}9>gX#oO z+K09CLH2M`W<7{mv)DL`%mwQoS`L2(JXZwHiSL2d)dfoPB$L1u#3Aa$U!AH2q3D`Y+# zBo9irAbp^E1XK=!+zv|HptdKZTmtpUp>_Q+P}>C5E`{7_0&)u|jl$v!luto*H>`dJ zl@*|RALKSr83~GCP}%^Mdmw$FybVfkAU^2aW>CEi+5-&g_kq&^be$l`Tu>PZE@RgA zfaeE5dO%_zJs@|0;tQ1KAZ$o|4)O~qY(ee-wUI$#0P-WqzaTLX4Uz|?FHjtU;vW=V zuyg^6UyvG*IUpKjK1e;t98esA#6fWh%I~1G1!9Bh9Z>!T=>@3+r85u)$${z-P&xw1 zf!b!E_ygrrP<{r587N(Y>RHg311SB1+y(M8I87G^{Rh#YI0MBEC@w*F>VWb!sE&c9 zOArlG2kQTW+9M!)Kz4)DAP9r(2c>CHcz`gdJp%FvD2;%^02D4DKZ4Q_$o-&l2~=S;Lho+|S1vKQUmfkC_RAKpl}7TL3tmvjtJyWkY7OI0+I)@LHQr#PZ$Q} zLy+GO0F^JGc!QY@O0S?a1}XzU zX%yrhPKB3XC@4-r7~~&N*#z<{DE)%m1}YOk;SMUJ zL1_zI4y`cY~ z@)Oi{2c>sdISVoa)VBhu2l*A`4v;w@zkuyqTKym7E=ajh4W1JPiG%zBD&Ik21o9(j zi~$rspfCpc9n`J@g$YP6B)x&|?Eu{yQT!it-U~=QI9{M-ILJOw_=3tKi24?A-vpe` zK>HU#Yb)ktgV#HQ>IG1^fWimlCs3XO#T_VZg5n%hmVoA4Kw$<7OOQK2egcIP*uQ%r z^)*Nx$o(L@LGqxu0L3q;oC3*#{09;T(IEeV@)F1{ko_Qcfz-m*BZ2B#P~HTk4N&<6 z%JZQ58j?Rj=OjYzt^lQ9kUXe-2bE7CGeP+jWG0LaY7cJ5;e!TPpN`43VH!=N|-*#UA3D9k~7D?$1}ZUJFXxP#&p6h5Fd0P-^^ zAA|f25(B5-wV?Ru0ngWi!UCiol;%KT3o--Lrh|!t#6Wowl*T|96jvZ~Kw%H+Yl6}m zhz+X4K<)t92dc9`E#P@4u-QG?;Pr42HYhDef!nU2GzQB1ptu6L5yS_X z0~)IZxepYtp!5I|2eCov1(g0lc?Q&80L48h9fI2Fpu7yy3vv(0Z6N(1c@PcC|DZ4g zVNm@8>WhKX75FSZ$k;U~&4R)fWFN>pP(A>K56IsjKY`o_3Qt%Vfy@P|2bm4>Kgdqd zm=*YJyB5gU0jPWfwI4w40GRcHs?v<7%DL*|G8+_LAax-9pzs2P8z}#S^nk(+l-58r zD6T>Bpz;6|{~$FWHYlthVYd~$J{J@ZptuF;0mU6C96@3rJ}9q)$^lTC0HrNZ-3v-< zpmqW%4ncK1h=#;JXuJZ1A?wdTc7x0S=>yTAxff7;f$}!Ue2_h$^d00R@gGzlg4BWX zHz=J?0o|*)wi?`?1BC%7EIg73ZauyQEzo7OYC|!Z}nu5|H$UmTX1nCF)6O>*+=@#TJ zP(BBxJy1M?)6`PPS&g9l1TqWcE|5Dx{sDy<41?MSpt={7??LGU6ki}W!s>C5K2Y8Q z#Scgvl+Qu!IgmKa{UA2jAK>#;*8T_e1wdwj!U3cgR7Qf-K74#FV2L2d-) zaS$794tP8OG!_8~Yw%bj=w4y)J-$=GXPbb+095{fFeo2`!U05s>;Z)bDBXg}2T&OT z3p0q{TfqGSP}+y&IZ#_2(hdNH9VpI0;RWg&g5n(%=Ad)|QVUA^AT}sIK^PQ;mZlu|f4EDF1`Z0oe`1pnfPQ&4T-Opz;=Y!HQ#4pggvjZb0D( zDvLnz14;)Vw}9LU%Ksq0fbt$F&w%bj1GO(e=^4~s0jUG|85B++HYf~0{syr@;vhAk zasb2!u|eekm|YwM-nRh?YmnPP`5P2>ptyv^6NnA+8%RG0gW?n9PEfi4=>y4w+yT-L zDkDJVg5*GApm7UOxduwJpfm=mV?bdDO1q%A1ce)@Tm#t!s;5Bd2NVvVI0xAQD&s-* zEJ!a1gXBPA1qyeNTfz20*DZm=^ZhY!UjgJUP&k6}KZp$q3y>a=TS4vwnGM3Auz}1c zL(aqp*$XNMKxV=01La?kUQn6@0}=!20fjv%&4S_qq!wg8DBMAL5X6S50jUR> z0csO~>;~m~kUEfgAaPJy0?lEAFetr%;teDQO6Q>R9+WOY=>e1{K=~0=2ZAstErP^B z`5vSm2kmnQr4LZL2hAaX#sEO>2DuH?4*`V-D6By40EGc4?m=xg z(0D&64TJ0hKL;F9lumG6{@&l+0 z1Ep<{f5B;UX$$y_L{R<$m1Cf?4P53HJN<{L0htL3cTm~{u|XJ=4nW}!G6NI_AhSXK z2Zal$J^;B3TxWsrD*)XGS`2RMgVGa7JxCph2IUD*9sq?K2!q5x;Rmu06gMC{LGcZ0 zV}iC{2R$94KFaFxWldb4MWUQjlLj@c_yXpfm?c zPcZ+2+zCn(puRGQ4Z|RLko!P12!s3p;)CK0l%_y-fZPnK&p>h@3<@Vu+=0>$$bBHU zg2X{-9TYbpcZ1Y`+z85dpu7wU2as7HH6Sq%4H5_01!IHU4Pt}h2Ba3m2esuv=7G!t z#Q_L|$`VjH45}|cc@X4ouzJwFZ^fW7M9}@D#o%!`P?&(!f@n}YgW?{XW}cq|-?a)# z6R`9Qp34M{(}VYG8-mv>g8Tsr3y@xrJ3!$EN=qQ~Kz4)71Jz-m@Bm>@dI6QcpuQ1k zoE20KgW?@jHi7H~r8!Wa6O@iY=?YYDfXoK@0mKLS17s&i43x$}Vjw->wgBkv&}&Qo zgX{*CeIPxc@CT)P5F6w+Q2P*+&p>r9D6fOs;2;djtDyV{G8ZHd%8y`wf!p|?@wu(w zF;tK~5Qg;|K=}ydPmnzzy&y9{@eVQ*WIlM_@7h+#+K_9Ib4EesE(n9d71YiE*$q+; zDs#YgLf5Q=!XD%gu=$`hrqKCKke@;R0fhyK4GF7a@SSuZKZ3#sghA;56#k$x5)=j? zF%TaVUZC~|2!p~9WDdwYkQ~S^keQ%*6_n0EX&j^u5=Wr*q?X`z8pu45I=K4kDDeCZ zh!64ysGSIMJ4g*EU4YUwD35^CGjzNdlx9J8fb@XE4wN=PZULzQzdW zc?6XILH-5hBT(A_bRH=PL)3uQx)H^ck}%BvtZfYgF8$S#mx5Dl6m0?qA! z@-CPDl9WuWTssq7h7)pT8{|BWlP>Dv%gR4itBwyb5B2^nv6+@d_$uK=~is z4y}&*4{95L>yVyo@csvI_?_GPA5`Ci)PeMX$`w#}g4BV`0re+9`atdjr5BL}3pkASP63a@gW?}#Hb^~49Vm=J>Og4^6s{mXD4sxKp!xzdmjsT}y`VN5WS>9C zPau0hW`W`dGzSN=2c#EdE+~D1;uFLMsRfw_k^{K|AfYJ$w4O$-z%736V1uD-#ZUDI(7B(P0$WBnW!`LA6L4E=G6_hSO z;Q~?v5(kwLps)kUf$|n8zk|#MsRzk{+9aU57bFj|4;0oQaZntC>;%GC0c}5(l{lqz2?hPWCzGEptt~) zr=W5fR33or1!0&xD35{62i3Qr@qLh=KzSUb7nB!4{sq5;oc3_7R8=(htHQHVlK(4aiJT8UV3DVF$t>|AEp7sBH|& zk03ii?gW)nAURN+fzl5s&Ov5^;sC@4^#?)W11eWQ=7GW&q#l$eK=A`g7oaj9w0;5P zK2W{~rDIUO2Bi^D840TALFoXLKR{_0oemexV}36#e{^*l%~XkHH#m!L2QwU0pg0<<eFkiDQh1!9B3 z6=Vh|&w$-k44N}62CteGmay!T!AU4QNptcl9Ehrp7#0QnuH55xzV14)O~;5*bn;R6agQ2GR=JCI!)POL^Eui`ul&?T$g5njFPC*zHHy}5H)PT}2hz$xe z&^j4V*#pW?pfUiIPC#x3#Vx3A1<~MmpHmF(--FBn%F$g2EdVmY{e6<$F-w2~r1g11M}jVF?OTkbgn>0AwC0 z{vmpj|AWd^Q2GRwKcF}O#XCqJNDat-5C(~X_#it#`ao$76!)OC2XZqgY(eIO)Pmdu z4s+-_BT)E(#6V_(%m=v_ly*UB9u)VWx)J0?kolnTAW+%|r4LZM9@HiWm8+n$6hL7H zD> zAQ}`#pfnCD%RzY`{x`4Uz}N z4J;3U`Ya%`KxHw^ogf+{1~L!C28A&wY(RQJY>=No{sFOJ;vhMY8$kXBiG%zEDhEJr z0EvUtgJ_VMAUO~p6b_&`0MVdw0i+g8L&pU{{)L4LEN(%3kX{fCPET8Vz->uTxePK3 zBnFCiQ27C}3#JxCgW?{XCPC+MfX;jcuYYa_N_*h(Mo{|>wAKc+)^YC~@K_kgJW$wx(jiC>$eken zg3<&i?}O$6ze{0>UDpu7T#bC5U)gWL`(Q$ZNyW{}%JZ3fUd07yT`?I5>- z(i|u+fy6*{3`ifyzo0Y;!XS5n^n&s?C_X{q4YCKMAC$)-o^ngsb5lny}g1zKMS z@-wKc0oeg6`#}0Y_JC+m+392{0d7x&%mVojES~KJJ|7cgC#c*4rD2e}Kp5mN(EKGR z9Km^VN-=niBq;BI_#k^gav*a+YQc3Nw0{TUgUSd{ng+2!Z3qw_R2GBW31Wl75#&Bl z83Hl~#0HrQayv*3NF0>s!0K9(!Fw}7ZU?Cab2C2?}3O zn1IS*aM@cN1P%j`7|72c4Du@?ja2^!wHHBQ4N4cFdI#h#P}u=$-+{qW`fKD=il$wz-x6t`2mzpKxF|azk~Q7401adL)Qg@@-K)Fk^`kr(3%I3 z9UwP?(ilh{M1%1;$T}f#{{gh#2h`3#HV3>f9OQnG`#^Sq+yQbQ$W5Sf3KS-wv<&hG zD4&4DKz!tQ0);iG{sX0NQ2qzyNl^O@qz;tlLFR$ffZ9T!G6v*kkbNNkf!qel_aOI! z#6f-mH$}&*-0?JQ>NN7x27?<$q9L z2jpf@+5`C)q!vVj%m@QV%i{M1$N5 z%2yzHkX;}%Kz;$mF{n)iYJY<6PXgHovKOQd6c?cI0awDkx0_A&9UIv9f z$PFNUAoqd75o8xAe}Vh}ibGKS0@4riC#Z}9rF)QGgxjkBgW6mm3@Up-c?vXF1foHC z6;#fH;vAF*KAihMhni*h7#blAfUa*ps)eOJt)pV=791Y41@9zpu7%p56B!)c!AV_%m&p5Fg7SIL3V>MD4swx$WBmrfz*QX7ASr|c>)yn zp!^3C2gNT4gVH3(Y>*yM`T&^+@)ua`)+yk=6v%!M2KgNnCm?m8`Ud1DaM%|^=5;}C zLSRT81M?@y4v>0~*`Pii$UczWAoqaEa*%x>IZ*u!YTtpw0orE(4MT5NG~Xlg3>D}Pl3chG>8u|AF{Rr zR33oRB}g9RUr_jg;s=C5;Q(?k2!p~G6lNfKP~8S%gW?mU2gC;DA5hr`3UiR(Kz;^= zCCI%Xd2l~&YY%uV3uFc;-avMOXiyk{Fvve3F;EzS!WZOzkR2d4$UmSu4V2G7=7QoM zRJMRHD7-=Tg2Dlm_CRg|#W~1qu;0LU5JJXQKxTvD5@asOO(1uI^nmJjkbNNcg5n%> zz5pohKFK9dylxIP0L(qP7P(KQ^HxktT2IVtQo&bdxhz)WNC=9^i4Z2^tCmC}8 zA^5I&um7MmC!jhW)J_7GW1#W|qzB|D5DoGl$bBHUfy@Q9u|f4aNDs)5ptJ^Z6F4tN zS%UK~ENy_~KyC(=2_UzC{0bYV1i24n2S^OG?hR57fYwtuf!ofY@&Oc%pl}0)At-D? zeg=tw!V}b<0ksQ2W`NuXDjz|1fiNhJK<)*p1%)xl{UCc_@da`>NDh=nK=lo1+#3|< zpmYUF!=Q8tiU&}h2VszTpg0Ga0oDh-s~%LwfZ_#Y2PhqZ!WfjkK=y&c9OO=r+d*j- z_?cMt}Z>mWWz4&+ym-5?Ay z2V@_J4YD7^2Kfh+j=*xzeL^6&faE~-f$|lI4J!jce30EB4C)Vn+L)kn43tMfc^(v2 zpmBUiIdBf#HvpBHAaRhpVQN5e2FlA|ec<&%ptkq0E|56LE|3~f+<-91PEdOR)aC*C5o889Z+U5g=i)$V1JnlqnGY)i zKyeRB6QFzq>hpv0A1LjE;ud5UD4alf2wVp{LD~r*y&!u*_JPU_5Dn^Yf!bW4_AY3= z2{exY%BLXvLGA|G4RSZgE|9xG7{msNgD}WnAU-G^g3=}kgUTI{T_6ndAE>Vd3L|iv zaqATDJ(Zwx2GrI7+W|Vur6(KQ?t;u|Le?gM^@G;qK-c|%+8dxS0NDpBmq6hNavR7^ zAag(%6y6{{C|p483=jt83y@hLy&yIytiXN*_fZW0gVcgBC~iP$9+YN4YC&lalukf# z4T^uzyfi4if%u>_0U9F$rBzVf0HQ%*3layhLFRxkEDeI{PY@pz4xqJo$KYp>uLbYL z1Em#^xuCEDxdVhjd{8`s|kv$a*)BdqLp@ zHVd?t8FYuxxuxKJW1uty(gVt0AUA{5g8U0g8z4JD7-T;#Qt&zIpuIpKdq8mo zk^|Lapn3<~W&n*5fc7IU?E$Za0?C2Yfcyl49c^h@C50Bl?$Le1j_#)8Z^fM z(hEvIpfU?YgW>~JH-Ok6^FV$Exfv8zAU}e_9~5sOIZ)pRR91o5pf~{K3y|MH;Q;a% zDD8v%57GlN1EdBNZXmNjc^>3OkUv3X7|8t~3~~>s3;=~0D7--B705mi289zy9%LQ} zgW?)w7HBL76n8K;gWLmRgYs2ZaU5&7d*{ly52EAag-^ z3zXkM`3~e}kUVG}9i$$VKS2Hi`4eOZDF1`b<^t8xAU}fa0F@0Oy&$tec>+||fzD|F zokIu;ThRS~pgaO{ABYCo4N7OAumR}<(V#R3&hJhV|3PzPpfCZc1-Sz>b^&q|2!rw% z$iEs?$#WPq8bY3SY|F>j=*VKUQM9doo zfzM9|g$u~MiE(n9_YmomydO>Lxl;=V1KajgXeuB8s5d1GyK}9|iS6L2d*21LS6qI7ken4&)aQA2bI6DnCGJ0K^B0 zgUkS_2ZaeJo>ErP-k6bGO_14ut8K0#?0WG~np(EixHbHMYQ zpu7XBJ3)4W!W~o|g3=%;{et))GeLP7WG`g=r3HL$BFKH9^bX1+pmYcdSCCyGw}H|X zC_RA2?m%@Z$ekdwKw==ZAoIcPYv_7nP#y#ELFpG{9w=-<@eQ&Aq!yIVL3seAAJm2e zwSz!x&^{YbeGf|0pmGk>h69!9ATvPa2q+zZ@)9UaK=lo1tPvDmpfUg?268_rAArh7 zP=5pDXOKHUc7ogjqCw>ZC_F)HM_}VOpmYN&!$9>vs9XZISwLoj`~gY>pfNX)evmsr zW`O(-^EZeO%E#a`&C3uxCIhNdK=Pn61=Mx{g&Qb5LE!-E1A*KHvJZqo=?x?fayuwa zKzRU^&Oqe?2!qXcQiPW^pgsi1&!DgXsfWa86nuR*$ShD=0mU0AEI{Ug%2<#XC@+Kj z4&sCKg3JNA3lyKAc0UM%(j+L4f@n}W1kqp&IwO2*4|r@2WG+Yy)HeZ{0ir=>gZvCS zml1R>D#%?RJ3$zf2SNECeDrEySr zgVGKttU%*@AU>$w22umctKjr<4|0YNC_jMGEl546tN>xKn*Z;??F3N10p(3lc?iq< zAU>$i08$6i2ckiHMc+Ta_aC%=62b?Si=exNA?J*O+zVcB{r((y{Uq4GON$}r8a_vq zO(3^`)Pm$e=?dgN5FZp?Ah&_i87TZfVGY8dZ~}!bDF1`hfa)?(7=!eJ_@M9v#UE&% z3uF$cYy-s?2!p}_QqG+N@B0Fkub^@Ol!rj=15nxnxdW8GK>h@!A&`4OW`gVm@j>c9 zWEG-77Pf$33>I9IRL3V)L3^E6lK0$qZP`H5O^!+hN|8Otpp5<)#7(Xb@fx--= z2NG62|3Ucb5QhxrraK9HFpKZ4YPXplZo+Z(i=5L9l!#6e*O>gR#d9Voql(jLeh zP#yrqAuP;6VGR-k)mXxuCKHWH!wIpfCl8L9!QkycMJmBnI*;Xxsr5cc8ou z3Nr{Bbly4S?lX`(K=}uh{y=d83MWwd0>uNUjseZZf%*ltGkZW{u=oMl1&Tw^TmUGnKyd`J6O`6KVG5!_br-0t0{HX# zP`U%LK^SB<$o(L{fb0gbLH+>MGoUmIN^c-BPrCX31ko}-G07&oB z9?%_#pgU9`^V%SDL2dw*8=!mwN*5r1g4_n$KMKlYAR3fzKxq@yb_Ll1aswz0fbuq| zEdr{8Kz4!50p&xG`#|vk(hmwBP+0;Vk9!W;Ck6@|Q27N;fA_Y6&!7RbudM~wbD%j( zP~3ph6{wvEawjN^L2(Ky^Fell+zGY=TIYho9n@z7@H9m+S&rn%bN>`x#49bh3dK#3zLGy2* zc0S0BAhSU7pgCAj`Ulwqv9tO=X#Edp9T>gD^-8oY(K2`wxl>P@f-^Zb5P&aZpxAoL1G{bFC*UX1)p&N3SSTgjrW1} zK`)&G$tR$20fhs|UQnEa!z~v{%U!d>+6E@5h%@r+z#>wC@+J`0Z400|oD9%7`1;r&OZGqAgD1KmJ4NB*r zIvrG=g6a&ATS0jj6ki~9ptuL+0}vmSmqB3zYbSuh8dM*G`uZR?C{2UPU$7g%caXLG z2gNVQ{UEo3+y(M0D4fA%{QF~Ic~F@L3YTkJtHJpn6qc~Fu|Vx4P#7S>71rMYl@-u-HV&v=0rD@%T_Ase;t5nQg4m$83rG&678K4P zF;Lur!WYB_)nV>WYN*|zb2dM*zf#g7I8A16T z6uzMR29g8m1%)ffFQ9rIR3;o-3OcKL3iw>8ty7}FcfNq?cu+k9s_#K+LFzzxACx{p z>HOSQNI3xt15o&Y+zhfG6rUgrazBU zXx$sAJ_LmYDF1@v^4wDJJ{wSYfYKr;%t2`!lx{(MP(B9be-Im#u0dl3pf)K;FDU## z`5#pNLh|$!@LV5A9SDQ^V<0skd5}4vHULNrq!v{6f&2~X%Yf_##W~17ATbaIjemm5 z%;(2?{)5UyP}qR-HE7>Es67Bu0}5}D7^pm$1HCT`)D{4Vf#g782?}SBevsLqumgoD z=qy=~94Nj)?Ff*1P`H5Fj-d1g@+&BOL16~c2TC^}8pH?17YKvm7aUgKpM%FUK>h=j zfuKAF%0Hku0OfxW28990&!BN=5F0E%1$0hZ%YRV45Ar|AK2RD5(V)Bzp&|Eng3JQN zA=tg3aY^u)(N^$TsUSCj(g3Io28AhToCq{N1~Lm|F34U`xdh6OpgaRA3qbaR%5YG; zfW~J*;vhXRIZ&Pf<$n+jQVa4E$UIP84RRMKeSp&scrE8z@E9qmegKsPp!PqgPYp5? zRR4qadV$7!LH&48o&=QvAiE*q47wi#QYM1J6pZ&y0k7uOoQ27LM56pd_FbC-YnFUH;pnMDBgX%|68U=+l$lahc0ZP}P z{0++YpmG4j2g!lr7$gp|6BO2<`W=*>L2@8ANG(VY2!rZB(AkfmvH~<`2#Rk|x&fI1 z(hrIQklR3R1i2gJ7O=avP640o3|e0Y%G02-7ZhG=dxF6AIw&kbVFkjVFr5NAcj*{t z{ICUlUmmEu0OYD0k7pnMLB-()XEa9Iq>|DZSk)xn_h094k1!Uj|ifWiXg zE=Zh0(kIAmptuFaH7MReaR5>eQVVG({r?YYe}cjlG`9)zBZv)>2hpH#0ExlM08kwd z@;?ZJ%m#%ahz)Wh$R3b9tlk8rBT#t*Dl0+d0LX5TJ3wrZ9uNk(1yrYk@&ssqAZX4A zlvY4t0FL8xOTl{$K=~S!r$Kc(sGkjL-+}TKh!4tFp!yUv)&x=qT1O0OSAxt3r7w^e zDF1-m3&!_AWzbge*$kkz0LZ)s4M`v6;wWf(j{2U+8*%TNuV$Sg((Pw z+IFBc4l*BvL2{sY2hkutC~QIL5mc{({0jElwK?Fr6qF7@7&K-Kk^_Y~2!r&3FsSYa ziG#{<5DiMppu7NbGpPRsX-jzh2c=a|Is~oVno{lbAC&e$WeF&MgVHD{-Gb6IDF1`= z{k^6CzrWuKQFm?%c>WL+P9Qge(g!H4L3tJAXOJI2c7yUM$bOiAKw$#%3y21ZgTewt zgYqs&J%|rV8=&+F%EzEM1m#;(A}qz+^rNIwXJ@;s=0 z2-XKW=jR$^%@3#y0M!|wd;p3+ko_S4gZu(=BPeZy@+c@wL16$2D+q?P*Uzm5ovjIB zgTe|_MuPG!D6fO$K;;4`PC?-dVuQ>8g)PVqQ27d~_d#}n@)9VnL465O82}OowWmN~ z1_~QcIR&b7Kx#pG7aSJQwUJOpP*(I7v7@)1Z5 zR91o90SZS@9D(cvzuWqGuxBFV|XBO zkUU5qNDdU2pl}C;A4m+8c0n}AERY?bZ~|z4glr(_s~2J zO3$D)4C)_%`U@a6AU3E@0;O}1S`ZDg4;1g9cmS1Wptu8tIVjzM;suodL1hFe?SuMM zp!y4xHbHI!xgX>nP-G6R%0Ky5=%`T)5Td{7w;3U81ybKTtXX`2plc zP&|V2E@&}(Pl#W1Y1>|2)8v@jq0J#t3 zPLO$^vINuy1*IPl289(UZ-d5WLE~MZ{0}k{6rLaq@(+v#v0>#Vhz+tIBnR>8u;$ghBm$P+9`@FF`aYZGhUzAaT$<8L0dQxd#-VAa{bo5tOb$`4SXf zpfCrYXBB1mAC$*IZ6Z+K2gk$K7VvqWAhn?S98^Al{0wSif$DmY-$7=8>UfZP5E~S) zp!@-`3v@w~SJGufwr%SzCGZcthQwf#YT zbI=$as9py71C$>@{sP$nG9QFNJ|Me5;S9*&uU4_JQhDkefhiKz#&| z`$6smr`Ky+!FQQ~+zASEPJPz^`NDQO~r9 zlwLsggUSbx-Joy>^`Ag)1Mxv|0LsIlvKSmsTYJE3AV6UN3JX|23e=YZ<#Cu=Pm;yWT9UzS3{Y5s!VM$_!l3j7@(-xo z0{Ic-W{@~2pMvT{a2SI2aP(yV2ZaMDy@AXI#SaLB!VVP1;Pef0JM>;@kQz{&fG{Zj z!R7i=kl&_&@5ls&F$jb7g7PWIZje7fc?4uP$UPvvAU}dI$W0)-K=}$(7J&GmxCX5w z0L3GieQz&#{2!E_Kzj>7bw4QogJ@8>0ZMzI@B!5cp!^RCPmmoTw}Si%G6OWW4@x5- z8q}5or6Z7DkY7RJ2I}*J(jzGDKyC!Z3n)xM?go_yAUTkEpg022pfm-^hoG?q$ecIG zf1rE=@&m{mkl#V-AZ$o`5R{j}`G09O_`EPsdIF^@Q2c<*2E{ul%t3lV`3#ijLHa>* zAb*1GD0TvmQ-kLHL3K7rEoh7yRCj^erl9l&ihEF-0F-t?;`ffVfXDhk;vfuC2cp5_ ze|tgeh_b=u2WSljD9?l94rC`N{6OUk$X%c?28A!kPoVS#YHNVP36y3*;SEarps)dj zEl4jYUxUIL#0JTO!WqT}_Y2AVeN?SMVJ0npluNP@aaV0i|D% zeh>{xYalkr98jAYR0e?Tg^7d078Guva02BsP~HW_F{m5>`2*xPke@*9Gf;j7g$tq50F1WWhW>u16*L9~nfn2SBPjepZ77f(APlk>M1$f4 z#s=995(A}Gka?hRh1m_t{~&QtT?)dW`~%8sAiKe7e=TTCb1k_30*Qg-L4E+43Bn+A zL2(JP3lxtaHmH68mG7YXA2cQpntuS%AiF_+1eHag_y(m1h(6H0u*bk>!GqE*D4l`y zg3Jb`HP9Rh$Za6?V108S_Y#8g8^|A^G7D5Dg4m!qhq({rR*)D7gTz4ggZv9)gWM0o zAU-IafW`RQE%|<`{S_704`5`UTZ- zp!5SOPe9`^pf~}gWl&gw#!EqBp!fy#>p^}6`5BbfK;Z*ogW3=vIZ!x*@&QO6D7}Hw zA*hcJazBU$%Y*t;;I)6Cb#!yUdx1dd5~K$dFQ7IjC=G(@I*=P6Y{-28kn{(N*L&dn z0^)<_Z9#fL^$@6j0Ofy>I4FKW_Jh(PC@ewl0p&+f{sDy-DEvU>7s&0P_yPG5R2GB! zO`x(7bk7B-PXy{ef!hC|Faq@tK;;1_PC)uWX&DrLAaPLo1EnvpIncf8pz$bBod#-C zfyx9>oPg2z*V*7tzi4RRwWPC)JknGLcB6knkH5Aq`@tU+lJ!tMd@^#rK} zxdr47uzL7>GGxytC~tuC&-ZKKbJ9U}fXXJ2TR?13n1I{_$^)Q03W`5aJb~&%Q2hte z4~iF1+5^Y&`(xm`7*s}p!VMI+AbTPCq6It_01AIlz5=-uG)Dj$-vf=+fx-i%4wQz# zb}ogKIUq5J-ym&Tke#3~0oe<34=7$i;S1^ufa-YAntIT=@3MN!U&XJKpL1-TcL zmOyy}lrKT?1aUX$?p4s-@D%X6P)K-GgV`W|!qkECB`BYR(jF+hK;-}kgVGg943y?T zVGObh6!##1fZ9YLw}A3FB&b&&I2L24jzUJYK$07`=(J}9k$>Tu9F9%vpK)ZYZz z4QdO3ak3$J9t0G=pgILK<^{4JR5pO@24T=R3n(qa+Vh|^0`fD+KOp~s+HIin5ro0x zs?hb$uyH_8eg>r{kl#TVlny{~1PX7EA36X7z~fED;5|X0aafQ$LHa=$HpT_98`35P=>yphQU`J`C|*JBT~Hi=`~iwz5C(-a zC~tw{0hBMnelB+U4{BF|#6WQeDhELQ1CU-&ScBpY6doWxs0{!LA5c7j(g-MRfWiz^ z$AIDklm|d%0Z0xMH=uDZ&{?{m@ByW9kY6C-25O5z?&1W+F*tpL?{)y4>jr8ILC#wQ ziG%D0#TTd?1JN))fa-pbJ3w^`$c-R>gYq;e4}sd$pzr|M1=0f&2Za$R+(B*yJWyK^G_C{cql4Q;$xh%q zkU;vtdU`;0?i6sp2^20M^FiqYRQ7=46XXUE2IYTH{SCsP@&r`xgXa4{W`oKokbgjV z6=Wx<{s7USFa?#VAag+L#6kW7r9V)a0QS?hz2J3&pzsIhvnj>kHEJL}sJ;NX1%i9P z`(r?910vo7K0^oQeoz>J>;}0TlqO(t0Sa?a_=3y;`3+RpgUkl`2SkJ72b3>Cc@Lxx zl&(N*7zWt~Dv!bCG<44nsJsB_1?dB)xpR;;e;~6!aSp2gLFz&E7^n>Zs%Jnns0;w5 zU633o?Sc3pcY^EuW1#iDptdcj94m(IO}+h=jD4+8Ybf3vQ!A_xOV17^EK*#~>P%mO=J`-3Qvw0m9cn_ZLn9_m@H8 z42mxh2KfWzCs2DCG)4j{Z$aS;s{cXlCJ+XPX|~sYSU7^>0)#<&LE#EA4-___cmwf4 zVGPRuAPkBJP~HcnGY|%q1>pQ&>;>*KgYqDFyc>L8E95?3P(A~NG01(Ov;^`8NDRaW zms{87fX4tpZUxoLpt2WKZh_nYOG}`10dmLMDN*2i*g$_8kFBaG$?*RaSuulpmBB3+GUV=AhSX7 z1Bw?|z5&H2h!1i%hz7?$bnOF74XDflt?vVs;h_8v3Omr+BamL0+d*<5KB&D2j(gBJ zC3KDzlx{%j2xLE~tN{5RBnGkzG#DBXbK8Ke$W&wywUAJi@d zr6o}M$qs_7Cj-fW!U<#^hz+W{LFz#93^EHe-UluNioL*NIw12v@edkf1l9eZvU_R(Pr5?x_8OT4NauS3=c^VYXAh&{O zP#A*32^20Mc~Dq^!UHr00Ahpu4hl;MhTQ80%8#Ia3dlZCT!Z`viZ4)|2x^Bx+SyUy zwPK*Y7|6|_G8EJv0L^`YXpp&}HWVmLg8U9L50o}QZi2)qXr1<2@Y*bp7zl&n2V^(M zouD{`l?Na;|p-0;vJ#U+}%L#o)RFSQJ}De+#3Z-ry#$9>;_>_ z+5`C!rXJ)zkQz|?1njQ8kbSuzaag_pxeufV6o#NSBq*#wc>`2-fa(R1T2Oug)xDtl z1|$zkm!R+frAbhHg4#5odI*#+LFGCmot`y6Cn(6P0Uy~dz?400zZJ%Qvw7^D{L$2rB| zdL9(spu7VLBM=+pKad_!+60*oDqlh6KZp$qFGv_n0k<1LVxY7F+9w7}KcI92E(f6N z`9SdiN{=86vI7){APhgW?Ai|DZeo%8Q`2YM?R#R0e?D1Bz>Km|R;5ZWDmg zAE=xLxdT+LgYrAb&7gDwvJVu7Abp^?f~6G@8{{sqzLp^Hm=Cx-Xo>m{YI8u`0NQVx z{U6j{0l6JiAA!Oi6o;TV0;P3On1S*NDE)%!QV<{1w*sYUP#A;49+b{O^KGy=0O<#X zBPdOP%4krT42m~UegU=LLGmCB${V2e0w}#ea1S_5K;oqsd=C#u9|(i;DkwdH&T9a* zEkJP((hn=6K=y;v%zMy2Y0!EnNIx9pMo_u|*$paRK>h+@ke@(ig3JK<3FJnQn?M*8 zFCe=>>OdHz7vvX^9++D|Vj%NCZUyCk5FeDMKxqb)*1_Wo&~9#&3L1j| zg*_-7L170fqd|2$2!rYuP(BC60jL}Y#ScgyC_RGG0Yo3gey!L3_5(f%iRv(gDQZLEybfAT^*m4{YyJ z&=_JdcuW8k-yk_qJptN(4=Mvd?gP0E;l;Xngd!oB?>$bymk)g>{L+w3)!a& zY6F7e6BOSdv%vOk1&uvG?jQuY8I+em@drxNpt2b>#sV4_0rihS_q2iP0Z?578oL7J zc~BYyr4LX#1C>3X`ViDk0M+{-yFmRzkXu1%4&+u)T!P9(h+QqX^n>z0NFG#%fXoGj7YIYtg68?wg2!Ayd{F)e#TzJ{fZ`HVhJ)+{ znGG@nghAyss9XotQJ^@7xC3GiNIl3LkQhh~#0QxN3TIH*fb0jw2Phmt{s!f7(AXX* zu0Z|-*#inMP+A7L8&uDO%2!ai2nrui*nu#(3~m9{p~c`m)1Ytzg(oQ9L1h#ut%1w{ z?H2=;VW2z!G7r@D24RpqC=NjB2BZ#@SHb)i(4D?c;C>s(O`!1^kXym=v=r3dEB+4} z&jrO7tnLQ659CfzUIyiLP&oyX2l)+@$3gA|xerv1f$}Z~WG*BQd%$x ziZe(&fW|5z?F+E`KxaHd_a=et1J!|`cmahuNIj@s35rKho&wc3V1I({u>)c7crIvM zy9K;Y9Hb6}L25wp4N6a-b^yp65FdmgVxYbtq|X6LQ=oVT)#IQw{-81dl(s-=4&-J~ zdH|&>5F4Zx?5@2n;Bg>OSpdodAoD@u;PkMz`afum0H_=Wg$by929@a`zk=crl=ndS z1e8xfc?uLyAaPKfg31VRS^}TtR1I!Jfb_z|K=BK58^~NxScB3QC=G!83yL#P8UvXN z5(kANC=Nklptu6%T@VJT2dM>>`=Gu)DE>h42ucs2^a!#8qz+_0s2vR!f4&#ow*~0~ zg##!|Ki_>!5Qeq2&jtE&z#x$^lSY0My4ob|a{)0l5{_ zPl1(9pf&->J)k%P#T}>*0_x*|+ytUQWdbOVgUT#WJcIpr4s`D@Xw3+yeH{dz(*WrM zl^dXP2;?u2d9eHn?q`Aa0E61Hpnm*4P&h*ND}cfh6t*A?s)s>g2by05&YeD0yp!5RL2eJobKB%k$#S4fHawmulaw7nUl0bhy+Q3XP`rTZW{~-?`~)gj!D8=^{RfGG z%2iN18zc@Y)4}!iUdTEyQ2GL;E07pSEl3@xtN_*dpz<1IJ}7O0>;kC;#V4pdfuv8+ zUW+L3`hAc%DDQyc9b6uq1J#LB{)6}+^FV18l-59T46+Nfz71qH$ekcHAaPLL0b+x~ z1XO2%(j$ls3MWu~3d&=k_yFa3aC|`5gMrExP~3sUK=y#xpgaJgL16`o4^X-S$%8P+ zY>>I2G6ZBUC=Gzx`JlWDiWd+D#TAGK#Rn*kL2dx`FFg??5C+9JD84{yK{Tk3 z3L2*Z=>yRq`#@;{A_uvj5tP3`VGhbWAh&_aT~K&~)PUNGps)qCw?TOuls`c2XAlPE zMNmHql>b3#0@S_-VQ=Dg!_m)Gh<1Q4kwcK7+~wQ27cf z6G7&H(k>|PgYqyae}l{ig)7KhP&*LhMo@Ty%mI}HAoqjHB@hk5ptJ!}4{|RkE8pfCiLQJ^#gO8=nr4RQ-8K0$gwWfaJrAPmme=eB~!dqC+3I0S_cxc}S|^&gZ!L1`0|XF+)vlz%{R4~kDve1Y;QD9?iY3{nS5=b-!y z%J<;>pX~*{&k-aBlLNUABnL7ZL2(R>PgVF>n zTtVRl(g&hJ_JZsHr6Z8pAT}sHfYTay9~0<48PJ(bQ^0GgK=PpVhM@EbY8QagH7Kos z{0=I|LGb`G6O>0mX&jWVKp4aa#W{$EgfVDr2DCO9v}Omgw;U8V;CS5&S}zR}hxGSB z=7ZV_pz;Ege?a~Q#R({Ff#MDnFQ76VTvtKY1Ay`{NDhQSX#qro@*+qaWCutuNYAmQ zkhTKIjUX|QI*=PdX2RNupz;c2Hz-|z$^lUR289(UEr7xhpnfJu9mvg~d;+T5 zL3V=j8pwa3ybFqBP}qXnOQ5g;g%b#a#t1-R2nrvNIuHiM3n-m}vcmmj%^c@cto4JxCwO zJdhfYnV>QNgh6>6s9 zKLUI<(7C1mLFY$-%2trQAoqdF4p7|yavvy7f$9&CnV>oeBnI*eNDV0dLFEF-t)Q|3 zl#W3D0f~X!3i2;#Zyc!X0=3~lWerF#B<>+=7eVP2MIfxBX56X+6Fa@)>P64;~V0MDS z98~^*Fi1a04M;7B4XW2c=7Zas&(Hk_r3X;_g5*GB0-*E?k_W{fxa{7#^gn293e=VZ z#V1G}RL_Il4l);%HbHq9R91uB4>}(Pl)piF4HO=rFbCx|P`eovHlVlwVNm`Dg#kD$ z_kz~4F9nY?fYKXC92Cc(wmm2hgVF&g4nX#R>TXay4+=w2o&nYSAoqjRg7PnDod*bm z`T?Lh0+2gE@dnZlYTJYC1!0hxAPjOJC@p~E7sLm-6*SfhW@lT1=Yc?F0Vs|^`atdi zrBzTm0@(+OHxM7B9>fRv4O9kz!UCiQ6qca835qXJxPih96qg|PfZ_|p2K9?U=>p^r zkQgYgKzR)m-yr>#$d09w!W95NmNvKyoxWFN?^y<1!UgXShc;-EMIiG$=paR}~xkDbWSb!e3lmQ+328n1h->bAZNaU!V46aurLFMNwybw zeHJKuLGmEGK=BL;b5L3UVUV35zk^vX%>V*bw4P+LFosi2b4}g>Og&dQ2c_z0W@X^vIFEkP+JjX9;kc(m5Ctt zg2X}cpf~{KYmnbS?gaS(BnFZL`301xL16{rgTfM&20&#xs9gu*gW>=bw;(m3JO~PF zQ2qpkGnfxuTLlVhP#l5Of!H7#)b;}97mzq8J%Q{3mD8Yb1EmE}JpghONFG$)fb@W9 zQ2GPKGbo*a@;_+22y{jqsD1&bIncQ6wK?#4XOQ1O{sqMaIA69z{Rg$HLE#GuYfzgS zR6m094=5Z#G${T-c?}fSpgt7H&!8{|#d!&j*Dq$bF!3F_<{mjB1cP zWN#Q~t`Iba2g+ZNGzLmT)!^|uP~HZ~f$Rgt7bu=VV`U(<;Bp3Zza@CzJ!p1t{J@@3=^>aae0Z{q{g*_9>KR|p?oPhiY3ImXTLHQh1{(<DKY_vv-HzCigL6jq=)E|45J4};rdJ>a!rptJ$g*z-QfXV=n zd%$4=%8%!kg4Kh}1mz7-KLwWVKxqP$FFOgJ*$$`uRVGti=9w;n8`5#oyf%=c2umk09P&xzE^Psc^3R93;kQ_)HBnDCsDuY38 z1IdBH66Al7`@m{IbA=$ktObp|K=yrr`evZC1BuIG@ER{ryo1eOTMS;$0iSdI6;~kbaOnNIl3sAisd(4HQ41cmc;N^v-M$ z9~8f!umFVvDF1@u9^_Au|3Gq}_6Dd72jy!}xPtOBDD8v79praVSpX_SAYlti6Oj9J zLG=p=gTz7M1F{$79#GhU>;s8`^nuI*$${bkY}fO>;B)~R0|40z8Y=+V3yMdOeIPv` zb3pkQpoY1%T>$P;J6mQ`29hApGcd0Lh>;(jw4RR0299aB- z!WQH%5FeCYKz4!37?7Vpegv5Xs<+P_+Y0VigXY9QVGRm1kRKu8HU)e>C#a4Fhws)N z`1&1CT>|naC|p5yfXoB&L16-_H$h^ccm%}{NE{Leps{Swx!u|D^?;zX0?Hqt^aXM= z2!r^b_yw5*3SUs3hqMc)fb%~{9%L@49SOpqbO)+CK;oeK3Pgj(3P5=oqz+^zNFGFk z_@HzNDqmpf2Q*#@YF~oVF-Q&+Mxe9^vK!c?JrQc zf%qT{(hE`#iaSu*2nr7n4N4;*F;JNe(gSJlfY#7fgYTvQwdX-`1WE%SyFhgehz7+o zDD8mcLG65y9Uu&<>p|%TyiQ>)=nQ*M+3)oq)UE)fZBV)e*$avX5Dmg0KY`*5lqNuY zP&|U%3koL?ACwkA`3dG`5DjXxgTz680_8Js833A#zXn=o4O-6uxvv)%max1G;)C>q z(hw+5gUkiF8)OE!J#cL+c<&V`eqb1+7vv_8JHhI%Z3XXN0P~^ef`Z2fq4hne90&CS zK=y#zKcF-KN(&%AgY-GDfpaqP<;;)2ZcE( zAA&Gwya3cT1BrvmQjohq`3{s$KyC%aD=6)N@-oPup!^52A5<=Y${v^;$X*ZznF)$# zNIN9?Kd21|5%U7yTL4NUAp1e~f!H89kUK%?0wfNy52POyk05!FI#789ibqhI0@)3c z2iXO3Cn)WJ)WFgbD2za3`;fNrTJTy^keMKTApd~U9Y_s0PM~{1L3~iz28$m^T38G2 zbAikSVMw@u@_IF7f51}EURKbY0&Jbll>eZ)0#JGYnGG@%lnx+l=(&LJL3{jr&@=>e57Aax+UAbp^61=Q{U z-75uB4@#GyG8p84P`(8D4HOQbFa?Lj-YMX5TUfpYiGjiuqz058K;aCM1L=dMZx9<4 zH=r~KVuNT<9s-BcHOM?3sO|>ECn!uoYC-0J>T<9|W1u`4tP7oVpKgcbhdJ~jJK^S5eWUV#Gji5XWq9OV~aoGYs z6B5*(0%4FD;Ii)dUhsXDpl}0~pP+CBg*T{vhp|EB1T1br?JiK;0^*Kp@c0@iUO@Um z`3Mx(pmq|doCb-3@(jogAiF^63Zw=S|B!kFqz+^cC{96UgZu;<0|ogHl$Jqef%Jm% zBdC228si1+n*r6MpmsLM9iTh`$|skkAT}5)lvUJ=MRADcaYhjybLN+KxTk2NIfWT zf%^2Y`UWHpQV*g*?f|I=mFXbAf!qYbAUi>FptJ`{hoH73DE)!L4`dcdKP>Nq>M2Ot z0`;vx?T5YpL49seI~>%90oe~S6Xb4?A3^ql>Jd=-0Hrffy$>p9L1SSc^FeAr;R|Ae z;t8YP)Mf|88z^6c(g&!#0_9DRy`Z=QiG$Jwhz&9W zR4>8Gbx;}swedmu9MqQt=>vs72!r&1^n%s}g31MuI*@*l+d%ptV-27(el56c0*n2> z2WErZ334+?Ey$gqd=Cmw7zV{RD1Ct97F0)q!W$$83NKLJ0);V%57GxttI#{fK;Z_$ zptJ^x7m$BJW`fciC=Gzhb$um;hf^a!#CghBd1aRw3tr8`jEf$}+s2Bi^@I4IA9 z^n&?oLHAC9=DCCZgYrH|3}glDroMLdk2l)jQULZM0`3V~Hih_)hg3g11whut%2`Jx#Fes0L+H4@RK<)v> z8z>$@@dUCDWDbZ1sRh{uVuLa0yeiOo?Q5WWB0+oH=KKeh-=MK$P+JZ}gWLgH69@`t zkiS9YI4CYac>=U98`OpY-R%OZk3r!H${V2m04V=}@)jr@LHQ6AFQ7aM3SW>KP+Wo3 zf#MewN1$~+pm+zl59CfzxPiKv5##lgXP&)|ZCs6$WavLc8LHQAcL2(WmR|SP3$V^Z=2AK=W6EHu4@;WGQfXoJ^ z5768VD84{y!1P+kI)AWPQ?kKlbb#swP@IFxXi!{(@+c_Zfy@B885FmmbOf>!6!sv$ zgXBQ=fXWC^+5x!(q!#2qP~8F=GXS-7KzSYHc2FFH%?6EEENubLA%VsdL32qUw?NcE z&Nuk4Dt&otUzu6mEj=& zgZv7LKTv#vFepAid{B6U%0zIOoP)ISKzcxRDmaa-1-1E?g3AGr8K5`=r7;i&jVXZq z4yvy~@eMK)WIrfvg6e6IT96$eaS#T@Gss*}JVU~34)`8bP?`eOIUpJo)*wBg`U(_x zpg07j1JGC?sC)v&8z_x|@;|7)0EH_k{6OIYG7}UIpgag_1As7S?i&YG$?F9eg?S@6xN_L3W{G)8wpglgD@y;Kz;<73rasAb3u6;6kZ_zfXYyi zdQf=*N+Te%K=Pn?2l*4E25bjtoCuW9!2K`Cc|Ra|kQ+d022_rK=0rejP#p{kACS2q zHpmQ+S`Y?_gWL)711P^3VsLTe18ORNwcm<_f5Qdon3VTpF016|J|3T#$2!p~8 zly^Ylpzp!pq;nV@k%(0C#!FN5+SXgmjGCdfQcTMv}qL2&{rlR)hPkQ^vIfy6*&f#gAU zf!Z;kumOj|Qpg^1kpDq$1%*8*yg}&;q#xu5Phs z@)Hz}pm+eC9|x-^Kw$%N2Ph4J#(F?y6i5sl-shJ72k}7|BLLt{8+teE?7$0x}O&=Y!k|(hKSX zfb0SJ2Q(%M3U82JkRC{wL-w|V)PgX`&!BVz!k{<;iGeW4y&yk;Xi&ZdU1x&i3{VNiJvqCsgC6t*CDfXY)){s8soKxTpTg4G;@?bU*eH-PK{xdEgH zBoB&bP}uL3@s`9oq_SYl7k#l+HkI0ND*P0~Ai6aupPQpt=*}4@g^G z^FQdUdB`0ThW|nR15o}49RSLkpzsG_P?-;k1CTkOybF>8VQ{#E&Rl}} z0hAU%eFRXw57Gy+6EyY+!jN$U$az2@e}T$r5C*vqRKA1E2AKz{r$O!pr2~*%AaPJ# z1B!o;I4nFs=^bPa$giMq2C+djB%C1YP(k`Y;-GX2%KsqyK|AXQWlqNv) zW1u*N#8Wc3oCk#~2!rebnGMPlpnf+fe}LLwAoZZ|2E{QrFP+;8p0fjut%K48sH_0R zB`9t{@d=7IkX}$cg7_c|k_XWsJ3xK|xfjF-iG%7R5FgZb1i1_350E>+@>_erd(%Mj zptJ;PE5PJHd{CJHvL93~!DvXjTMNDi5tNQWegpXd6lNd{3UjdD_xHeOYJ&15Vh#|} zmItW=`3Dq+AT~%32!qNGko!St1ytXFOtZlcY@*?6rYg%3ppDA zBnRf7gPcDIGHWkr9uPEU2pXrpwiMdO2KB=s`~N_34C)Vn>LO5lg32{eUI+0(G-Mqm zWS#*O_aHZb+P@$-gWLd$J5YRp_+Sj(&j`wMAa{bzS=$1hI|i8#3RjR{LG=YF3_*1e z$loCKAag)*1Bxe5ynytA%!gr69D~ves2l->Gbk^EnFqRu z7Ssj+m3^SS@1QgXT5}2tGfQ92i zz;Up54!FMuN=u-)1Gxtl2O#%>+7F;|0W|&wDo;RqKz#~OUI*nB(0Dv34};7F=>?@1 z5F6Hh0GR>u3rHLkN1!wS(gR9cp!5b(3u?Q8!V+XJD4l@90Yrn!2~aqL;uqu}P`wJu zbD+Efig%D4sJ{rBKL)j5Kx0OraR^Y~5me@Z;u)j{q!tujATvPj0i_8L4Jv;@aRS1i zdIHpL1Gx(nz92S84XC{Z5(DKAka-}tg4&g!um+_mP+Wr22#gIX7eH|c%KxCc0u-j8 zvI!&)ayvLa_D+GeA)>(R06=X-kXu0Y6v#Y~8j#(fcn6Jlf!q!1bArS`ZUe<1s0{(C z-#}|&VSWRt1C5J;^nubN$jvbSgWL{s1Bee&55b`JQV+P?0f*yz$hi-o@)#7CAT^+{ z2l*A0mq2j`iWg8kg5nBfJ}9g~G$@Wi@dlCuVURjd`T(2N1G(Q8q#vXPghB2BnE{G- zkUG#<4OkDj&r%I8qd{&0r9IG`Fetr&`k;_L52z0h+9M0v69Xx`L3tn47Xq~tKx#l~ z1ms^(Sb)M5R7ZmR01^Y)4QdO3*r0R?qCxo*lvg2X0dnUOD35~T7F2G7@+Tul%7F#2dMo43OA6SK^T;_KxTlcTipixgV7FKxGIhoI&k)P`d+!L1_w(L2K^Wv_kQ+g93Njz; zz827(-jK6LV0uAu1X2TzC+OTF$SzQLgD|L!1=$C33&>1Rn1I{}W`oz9fc7Ck=8Zt- zBY@%qlr}(l2o%ns_yDN~r%}-P7SMBkL1_n+??E(34=Bxn;uaJ}ptJ#sOHls|M1#T; zM1#@G2I`-J%mV2J zrA3gL;QZ18nsW!8@CJo7D7}Hg1B5~G0_wkl&dUbHA1K{{%5qS+gXBSZ7gX1P%mT$FD1Cv- z0Z?zKBF6yZb5zoxfSF-P=4LI6m<7-5V+q6G7A)5AUi<$0K|ux2};i(vqA9+ zN(Z3y24aKMfZ`9N9#lVq(k&>yKw%ED4^%&b;uK^rsLcmXGtl$7K;j_vApe5$DX6>v zg+E9yDF1`KiYrK5^nmw-fzkvBgTz370_g*#Ly)^b_JP71R7OC;3v_4r zJ@6SmpmGKjb|7^i`$6dh$_-eYfbugaoAKZF9h174#J=|0tkcJt4pD0RDt3i6o#O@1xiPtZ~&!uP&o@qgPvjdFP~cq-kS}ITTmQAFl22sB<~f2_uYZUA3$|4$ZQY>#WP4hs5}A1 zB?yDkDJTtq;uIAApmYODOQ5g=#VsfvKx|O{2d&=&sR6kQl$Swe4Tuk#?*Ns}AU4Pz zQ27PPCy;qskR70S0Lg>=4a&~xd9{x_D>7w{u4;Q4-_V#cmjnnC?A2`35s7(*n+|g zVnz%241G{PA5wotfzOx&$J>hf(Asp+e)K5t{ZybbALK4j*#OF`APh=Bpu7l*9}ouRb&wgL zFa?Dzs7wHbBgikH_yPG1)b9l4Z;*RI{s)y^AUA>P8&KK>rDagqfYKz$zc7D;;uvHm zNDLfKYeDmkYr*9Ms5}JiwFT9op!fjwzhQ9#idRs20F?nCcYw-$(0)!xeyRqK8-emE zXx|n{Ehz3laR~~0P`rWS4^$R_*dTv_(hVq|g35Ie2IX^*oglY?;uo}54U~65=@}#k zQVS9XsR8jp=0VzB=OF8fo}UBXCje?QgUklC4c@=M_y76xYyUyz0x183%zXd+-hYt0 zx2^?^KSKHkAoqgQgTe^pM{pQ}&mvq39w!9F2`JBkFsN+~YNvzyfY+9S_veAcKo}Gs zAb*3*0p)2>dIPy16epng0hJ}7d<+VAP&xp`Gsr$rUI(>1LFR(e0VqB}c^A|_0Hp&^ zT!F$7R8NBP4k!#jc7W7^#6jr+WIn_$L-6<*C~tu60o}a`UXuqo?+m0Kl zyg?WgFQ9M$(I5;;Lm;&v`#@?zVT-}?kXjH8G7r>F1m$ax zJg6)HmF1vv7gRoj)Prb{IiPq2VNlrs!XR@&W`O2=!Sj2da=IrQe0B$@+yRHh-Z|hk zq#%EQ(laQ$U~O1XT!F#`RNjKhS5R67KF zzd`+dP<(*;)gbdga*#Z42tL0JHZKIS7qkWhR0aqLaQv5$-~g}X2k8f?fz00ofy)_? zU7+z^kQ}It0J#ZlZ%Y*9?(mkV|DbpTxgF$YP#OfqH^_aUbO+*t^nlzAN*f>yau+Di zgYr744FHON(D)X}U7&Iu6keb>1E~eo5uh{!D(^sH21eTR0e>` zJ5W9YST5?c+0@0xS1d3l!yo1aE=>gTppt1uLmmod}L(1$P zXuEbVxNZcAgUkh`36OeFdl8fuA^rQk|3P&fsNW7sJD~IhvIEp70M!wov;stt(hq81faZfia|Ph?0JK*08fY)kbCB@=YuAo}$E!i<4&+{tec&;ot)M%%*Mi%d z;IIde?}O?TNI3yYJD{-wP}&03&7eI5;Ie!#Wc>yx-avi;rBP5^g3=BsEIZ`224n^(oq{lEoCj16fYv~O@)9VogD}WGP?`p% z4N#c?Dz8Ch3@Cm<;-Ihv#Xl$wfy@KB4dgFS*$s+EkUp^eTS0BL7I1qVq!*+Xlr}(S zfWjA)he2rxRGxtJfZ`OyhKvh<){%nFsREr>1zBeYiWd+D*$>hSvJX^NgV>OuYhrE8G=ATd~d0&*v)eFkz9NDU~z zfaJm9JO#8C8FUT`==^_3Jb~g4qz;sqK#G2e}gzzMyah znF*@1L1i>JpMut5f#z`6LhiEy#WToUP?`bh1;r`IERa5sI4Dno>;uVx^B{Q7G-Uo5 zqz)tos{29d0#wF;$|O+P1d;>k0htFn!v&N!Kz;-H7nG(z`5$CHsEh!mHxLawS00pa z!0mu*$H03EL3V)r4@!feJOk1P^B>5sp!5MMV?Z<{J%Q$`A!osW)Pd3rC~bgfSeXuL z6M*s?DD8pr4=8v^NF3w_kQ$JCKyd-$gTe_EKQJ+n8$n_qK8Ob8 zTM!Kj4-gFsLs0n-iaQV+q!*M2LGqCC|GkiT|E*KN{d<@?kUYpvkQtz~0>YrW9USgc zAm`76TDBeKv19CqoU4r5l6gMEVK<0qhpu7%ZgWL(jATdxH0GSKQ2M}@4xfzgs zF`zI2mD!;128AIgt{`Cm>YqaH%K?dl)Pdwc?R-#P1?4ADz6SNrL1TcRG9MH_AR3g< zK=B5mLGcE{AT~%I?l=X_10@G3Le8B6jnjema?JtfYmix>x&q`5 zklR3h1(offatP!fQ2GYB0puPK4eFPGXizx>qCx9RK*S3QD>YzR!sO<>qvxD+3$ShEtgVGQve}dYFAR3geKye9D1F{E{MnL0IAU}ZW zc2FB0WDZCiqz9DuL3c;M(g~=}2bm2@AE0^-6mFnA3Mv;s{bi6HAish93o-{}E~t+H zN^2ndKz;@31!0grP+Jm|u0Z|<#SJVEfyzEmIsxS|PX@ z$Q+OusNM$U7tr_-NFJmY6wjb}K~TJb$_`Mv0htA=i$U%L&E0_XgW?O6wm@kFlny}Q z1`0orIUut^eg>HZiZf7|3i1!g&0ss`K<>`~`3Y2ZfZ`1lzM%RWG`<0{2V@q=Tu`0| znFERkkb02aAbF5|APf=*nF~?}N)w>)0+nl^a0SH=C|p757L<=c>Oo~H$Za5fAQ}|j zpn3wNA7nl#U4YyIG7}^ZG83d0BnFBXP~QO*FCach9%Mc!-azU>?E;XSLE@nJ2Zc2# z|AW#6$PFMppl}1#-=H!SdGEJ_EJgKxqP0u7EHo-@)1hpm+g|AA|IO^1q=X2l%WwP<{sWAwYQ+)Hi^w z3jxJ1s4W3%OM>)*`~zy!gWB@oa==Ry+@Ax*AE*ogxe;VO2!reZxe2sB3FKB#+W^!~ z0EIOuUO?#r6xN`;57H0P1B!c4ScBT@pg0D_8Au%{uYmaAGy!h+Le4A!)oGym50u_P zWf~}ML2(G069&Z}s&fc1m+>VftEfc6Q2&u+*Dueku34@xs2dqH^^6rZ4c32Fm? z%mBq1=sX6{oB(L-0i*_027&T5$S8L(m2Qra9q!60q-jV^{qka0;C7zeh>z^ z2~?(o%>}Jt0J#Zz{tHMBgh6=%lo!BtJk-A+e}OP4-GK5eC|!ZlIVfF$;v1B9Kxqq9 zr-0a?JOhd|P#FQr#~?Xa{s+l}ZLGcI*3lIjyKgfQN z7zl&h4JxxhW`M#Iqy|(@fx-o(4n%{@1JNM=gVccH50sZcaRQ15kUCIa2aQRB+yOEJ z#0IrJKxH{7jzM`Aq!;9NP&k14FQB>tR7Zf)B`D57@*p!oWdJBG!1RG=P`H8gfz*Tg zd>}V~^nk(^WHyKoN{=8vf%Jmh1PTw38$kX6(V+eeC{93O4st)J3@@+m0(Kyd=n1By40TCiL(=zb2+-VD&VDr8?isJsE?Kad`nUQif= z@+e3TM874t4FJlAFfmYm29+P6@(1JwP&xpa1#$<-J`e_pf#M7l7a;RNY9VP5b|xU` zo*2;h0jPZn8PA8*pZ~#UD1q_^C_RJf2T(l?3Rh5kf$|loYzBodXxt8@1{AiSbO!2o zgUTQf8x((_c!G@eLH2xr(grBrK^T_zL2&@e*Py%#%JU#|LHa;t4JbZAaR-VoP#l59 zK;t-bKzj{A<2yazb|k3W2bBXLwIIEqG6GT->;<0<2r?T~?||$C&4Yo)U_tExP~3yk z9mqW(H-j+9E>PM4iGgU4n?ZRHl;a`WP&|V2J}4eRX$w?t zfXoA>6;OEq;)B+Ag5*K<5~vISxd)VvL2dxi;B)}88+2D^59DqdP~HQ@C8$phax*NB zLH2_5f&31_;5rj@R^gmt@K`=b3}in@9k`sBQw%<*D0LSaSz2GrokY7OI z1=a^WUmWCTkR2dDgJ_UED7-;w4dfP(I4C`U>!kmnyIrpRhq(`=7Gw`dABYCUJ1DJy z#6fWkDr-P|P}&3a0YT%2pzm5pzs3KtDx`% zGmKx~kHkUAI}6sMrP z42nZgTMjfw1nReg>RV7egWB()x*C%Ay}*0_LE#3<+aNnZWe2Fg0cxv&)PvduAag+O z0I36Eko}gYpb0Eo5TplGUW4*HXzdrM+y>Dgb3lCqP<{uoA!4Au%9Q`0JPvX<$Zepp0MI$X z5VfFuwiZ6-4;p_2r3sK6$ep144QjiC(laOwKw=>Gfy@D=S&%zGGzf#z1*j|n`4QwM zP#OXG2jp&$UqEFjD1Ct9AA~`2p!fo(pRJI38e}fWPEcHd(m5!PgUkW7;UH-PbSDF7 zJ;+jUI}TKLgUkT6|3K*jl;%M307?U(dEOKKcqADK>h=TJ*aE|l~2C%XWRK9`C1^E*c79cl($|_Jgf%zZA2KDhl zYCz!$!l3*Qk_Uw&s4Wf(V^H{k>R3>?L-Hl$EC6tvLib34!VZ*%K;;UE4Kf3qXQ5>X zD4sxiLHQPBA1IB2_#it$_JGub%L35d=-~0nDgQy~0;CUQ56BN7b3t_gC{97)1d20I z`Ulwy8pnc^ec9l36QHsgqz2?>Q22rLfWi<|4uJA0q~7-W4~j!jxPtNp2!rw$sLck- zi=eRrP@aK}6N2h-P&|U_Y*5(&;)C>q@+ByqL2(L_2iXCd>jC9+kQ$H}sO0~Js>xM#6fn0`VAl&G)@HCQwF;0161CC+6$m@fn+BM@VOEozku8a3L8+l3n~Xd zVFd~cQ2c?*B+xyzQ$Ta3khP3V&E!g2dosRZ~EHRM2@-pga#6JA|G61Ue@Pvga41 z9@O>&#WAQ1fRz=X`UT`K(11S3Z=n1O!k{1h8bbiZIVj(Q%4ASK4I~C?Q-JyrpnMN>|$o-(a2#RA+84c0{G6NKLpn3x2c2F3A{0w4)>I_hrg31gK9~ADOG7l7PAURN6 zgVcle;(^j4Xxs=?MuN&mP}qUWERZ}XErQg8*q}HA*$pxmBo1;vtd9V8$2mxu530jJ z@ePU}kXo?5wUBe8LGA##5fpBqcmdf3G8>czL1u%>DNtJxRQP~8oxmqB?H zv`!3^uR(DHG7p47W`SsM`qsR5pOh1CY5OGhyWd zC_X{u4am))_5~<^gW5`v^7|OLoCL)u2!qN*P~3ycEl?T-#XqQ?0F64N6C#@CT(OP`Uu6b5PiV_@M9yu|aVO znrj2izk|wTkX}&R4%F`l(I9(4aSO`pAU-I+gYq3HErHSs$UPu;f%bZX>MKzG2fOPU zWUdgD)<9(dC?A8y{z2w|&7J~k?}F|cTnjGGKz4vIBtJp+uYk-2xd#+>ptJ?bZy@_X zX$+K}K>h*cVGss|At)>%;$Gl0B|zy1RF;F}Kzc!G3X~Q>c^S0+ALL(9zY3HFLG!er zu_4g75+t4>Yjr_+A7TcmodcRvgPdm%G7p47c^VSVYr*H`fYgH08^~@@y988@fXZ7? zn+TMTL1_V09)a8dau=u!0QKiU_JHCFl!rm_0x}bXLH$5boPxwbVFU6XSR9ncwnFaJ z0)+|4Eg*d$4B~^zKaf69o&)It)!86%5F0eM1IlM0zk=cyq!)xi_JiUHlmo(7GO!S3!JGx&o;M#XG1h0I@+B6knit2gMOcKZp;~14=s}_k;9;>;lCx zNDW9FlpjEG3o5%naRnNm1J!w;c|1_Q2IVtY9s`9Rs7?jdv7j+`P(A};(3lvgtq013 zpn4s&*AtXCL2&}=D}dS&AaO_@2hAZu+Uub3hvesCaJ~nX10W321L^~S$_7xr2bCWn zy&$!q_5jE|Fn58<8c>-6N4WdE$8e~66FQ~i)#S^IS1#0tw;s9hPsGJ9tAFw_EBws+v7*HMpsRzf^wWZ)S z8Xz%{T96nh3_$8ZY>;`Nd;{Wx!VDw_auX;FKzxuKNDT;s)Pu?dkT@v(LE#3{2QnMP z2FruTUqS9z3qJD^l6D~HdxO+~(h*1<$Q}?M#0I4!5C+8~$SjZ;hz)WFNFB%xAPiCu zqCsMiFgXVP66)GU(hWPB8MABYB( z2QV6BFGw%QY#0Wa0g7*sIIPS8*#k-^pgA)T2BjNN8x~aNfiS3k2hBx+@;oTbgYq6I z3?OV!-~BzPXa%pC1Lb*G9tW8T3TIH6394^F7?jRH;*fM+4PN^M@*5~FK;a8&yMn?M z)b0ZDL3%-Y!2N@Bd;f#-D=6=R#ue5so$?=4cZ1RiDF4IbYAfj6pE=;QeV{S`RGxwI zHmHmO`3F?ygV><@733F?Ik55pR9=Ak0H87iG*$#F7eHwNY7AWn2AnN3U^T4f&2+_FR1JQrG1dQL2(2sBS30E?FLXD2DuGX=796> zR>-+8pgaV!6BLi2umhO|R(owLcn=TAERY;X3=~cv^`Q0a4WPUX3VV>fpmrN5|AG2vpt2d1$3Srh ziWgX3gQzJ6pFIuApCAnG7epC?`vjo83n~X-dcfwbg{%n%)!U$P22gx~%m>*E;)BWq zQ2qzyZIFIY9RRB5LG1xh-UihRpz?^*1IQ1c@c|GYl=eYp!u$tvA4nWz2Z#o#2ZaU5&mgs+ zI0wZGC|`o|H%JWB{{@v3pu7o+ACQ|s{Q-y>E#UiuKy6HrUQl>~^n&9UwEz1UXpJ6Z z?<1%`59*hL@+&A0fbuZNd!?o!a5Dv+~c zL16WbJT8p?8a;_UFZ-eRz zQ2qzCA3*sQWG~20P}u-77gWxGXpk5PgVu|H#tlJb0f-MO7eH+aP+10YC&+G)8K5>S zs9pudH>gek^*2FvE2ypnr8!W!0K=g6Bq*Fgl|DFrKxYtat^N-hD+c9pP`(3&J*bQT zsRM;2D2;>qmEiD%t`!8u11LR$)Ae4+U67#h5l~+WbnXtQ90$casGNEK{y8{LgX(Ee zeG6)*gYqMY4YCu&2DJe|;-I_@Dlb6!8pH;<^W5IG|3P^f?w$J&@-K)F(g(`_ zp!^I{2W}g@zXz5FxdD{lK<0ojsBQp-5y)SlGyzKApf&Z$N1j z6h@%D1bC~{*0yIJD)*m1=N3lwaFoQ1+w1=ls7=(3yNbpmGT8Z}7QNkh6M0?gzyq$Q+P)V=`aanP6oNFG!sfXW+Co(G9T z%AIWR+&(C;f$}COenDe^AR5$v2gNlgJ%Q?XQ2c}98B`X4Fi0J!900X>LGqyV2d2+$ z{ST`1_pXKX55Rf<`L+KbIS?Dvw*aMgP`LnBw{_`%NS=qRBLL+MP}u-#gFxH?Sr-h_ z2Pp?Yd-tNi?gr&4P@e;oPeJa7xe?@7PVUNMjL1uvL28BO}4N99JHVA{v0IPxC9|1BCgFo^FeljVL@CG^h^?3I|Y_ zfx-aP*Kl%z^fy5DG^pGGz5}@xln+4de~>#td{DjzsR7A@$_7w= z2DKGH>OdGYF9*rXTmOT`??CE7^(aUTWCqA=m^x4!03-*pA2dDyvInFdRHlH&A3<`U zG6vLc0rf3Fd{ABosRxw>pmqc(FM<34YCC}J1Gxp{Hc&bS(IE3c;;=jcN?V|^7u5a% zjSYgzOpw1o;-K^cYIlOuKj?fO&_4P1$G~@8K+-8_pK~&}3o-WkAc*{@)Jl6sGI`%86*aZBT&8qxdX%pwL3xPgW5wNcYyo|@;^vDsI36v zgW2G+60~377`R>rg&WB4AQ~hOaRX>Q7RaxVy+t7NVB(C2jzDV4QdB~%mS4Up!5Q2M}hJHsQv@R z3n*Pf()V-lmgZkv4IvRvQWdW$X0F9l4*V9EAg7+qY@(L)NLFF?je}lpaR9=GS zqCsU6Xlx49PXNt-fWiTk-oSKm)PHdQeCr%=oeRpBpgImz27%%XQip@?_yFDIb`E?d zJ;;5axCiB1P`U!KK^WAY2g!lNK>9#+87Mu2`T?N)2g-M#ybQ7rlGj1^k{koK13>L- z&|W`Sc>yvT#0KSYP#yu5hhTSs`v-f$?FmqO0hI4SG^pGG*$)Xzko;Q68br{3!gHYc zw>keoZUVUzly*V+1;hqnP`&_#GpJnz>JNbOJ}7)Z@eWGIp!5z-YoL9J&-a4cs^Bzv zZYg+g2B?e%nF&fCpg07zxj}ggR2G5!4Qi8s%mAfjFbzttpglOy`?Nsq0FXVPG6AF? zl=ne=P<(>&0H}TinFEpog(pZ3l(#|VgUSk!JV+f#9#p1+>;}aFNF68+L3s;QZh+DT zsE-K}1Gy2T9#mg|@;juQn*v@}0dfb#9?)HHpt)E`KOLk8WFN>MATvO20?}aeq3g*( z?f{iTpzsCR4{{5rKML{_C_RGeagZFS9Ds!(%p8yy$St5S0>uF+&x6{jpzs0d1?6GT zJUEC3?IZ(a?wF^Lb092QQ+T5V@51RJ`#W5tWMuE?k0kz*i zW`WEE#W|?Y0BYBR%mA4QqCt8=X#rHWgWM0wLm)Fia-eoMsGR_s&jYmsKy65nJ3xH^ zP}u>}1L_xm$`nx90+Iun2XYfgFDRTr7!+@yya!6_pt1mz)Yw}9(=@R|PSAZ_64An+I-$gkjaLSBa8^?{(c2lWA3s)NAlK=}|fiTEyP+kYA1F=D20>bBx?fnm`=RtWLR91lGK^Qbf z0dg}a+(2?*bI*a)&H=Bb0ND?63&>7T9tF7*#0I4?5Fg}6kh?+RATf|T!DT_R6Zl>g zP&k0n9?1Wov<)g>KxRVHE@++0IdFRbl%_!#eYO1hwly zYC-u7WF{z0LCOx$Jz9`^GePZSP&)yPLFL(J}?JmK(B09OM?TTi5o0%SlMT05oO@xknOY zKB!Cqg$D?O!U?1v(7n6hGpQhJ zCqZrol?C9k<@q^qxdh6ip!PJVYyjm=P<{gCSCBZUP6x{sL+)q-T%GTK9Kz&vq2an22u}d>%+h0(k_W{oS&g*fPnHds9XTG_d$6HRF;7B zg4BS*2_y#+1GOzcd{Ef|D$79Tf@o0L2Erh}f$}S;TmYphkefl{0$>_CUkP$IC{KXW zFDU#$_JPJ0LFz$bAU}iJ=Ab$fl#W4l8K_JKm8Y;e5u_jFcaUC?7&t87L)uHAxCO-z zD6fLz5>zLG$^_8304VQ+$`{aBAt;%=-AUO~pM1%4&NG}M3(gq|i9s`fXf%u?0 z0z`w#bx=71atp`|P(B3ZdyrqjZUeVB&VlCuLFz$n0@0xO0r>|MuOM|G8dP_JXpmVT zF_51?=7G!txdS8z(hG7MI6p(z27}5CPa=>c5Ufy%LKptW6d!1J9T zzkt#OsEq`!f2U-F%U#g86sTo{|inV+7d^YDa?10gXq3X%LE!^SAE596jmd%XGpM})YU6;~^5Al7X*PK6FlgNasE!Bae^8wQibqfwf%JmL z6F?YrrU9tW11k@}X&-bZ_c=t{8x&U{42oM&oPsc@4hO{H<)C07`S9egr5_gUSR@o(Ii+g320DUm9Z1Iq+RGAUib3v zq97W?2bm4l3%XO~8sscfko!Px0F{Lx8ic`dGN%|k{{-?AD7-;=6eJExC_~3j8T30_O8+>;lNDR~$0F^HwHmH6D zV`Wm3N1xO537J930A0KU|?VuU|?WigklErfC2*pgCkTci2WbLMk1I%c7Vi?@c&UT8UmvsFd71* zAu!}a;NQQ$|NsC0_y6C&e_+3W=zn1T-~WI9{6@mRkk}ycU;qF7h0=e1|Nr~<57eB$ zAl?5l%mtf1N{oiUXb22M2!Qe<2><>27o0aiG$?=n{{8bm2><%^CX2Ft(be2_RY{`vC< zxQ+hv=lB00{Qdja|1kXH$2T||B!RIw((oFsM$&#EAR@>3hTS zA~OB$+n4_!49dG88X156`uRT$gT!HM5KV{=QiF`KnGX^Jl?}-50r3&;M(tmK$~I8B zfQf&B$1y-*0~)^sh1Dn?4S}H^0-*d3@&l;P{^!phX#Eb!%b0lpA`Z$susj6HSD-uw z!=U^K%eNr<%a>38k@4rxAOFMfr_Ue$fBN(R%m>jhKA8OpA_r!F{s>kFm&e9OG8frC z5F6wUWOu>b3Zp@O0bz*0(8~iznFo>sg$IZRwGBXF1qwG<_<`7?cr*ltN(g|`EvPO7 zrDagM#)U!Y9V7?JA21BcH=sNP!pQjwl-FQ+8$^Th>qk&N{`}$p$B*y9c^E{4@P`lY zz+y1^{rk87LHOOfH((mX24OfKCJv+Dzx@x=3&QB;fyxY!7?=jz|M5S_Eg(06Fvy)S zcZ2+Zj6vlY%%30{=6_Ha;KGo80;~l!R8qjGJ4aFofbu)YzaSb^*Q2Lp!3UVqG9<2ly^XR2!ug->=U#;2IX~7z5`)Uz64=V9tPpJZ(sih?K$qME|Q-FaE>I4^X)Q!XP)jefI`j4uRYXDjPuV2bTxX_6f*;Aishz z$lo9g3JVYhg$JlC0EG`|91}V3BeNlGD%g0zXuDvrwx*6Z-R4a#?~Ux4%H)2C1V z-@1MK|H;#5|8LuU;Qx})>o;!vfAHYm|0j!zf9M5CFCBK^Qb&2dRf3<5#eB z2}-9R464UK7?hSl7?iF-=^K>JK^RoGgYrE%FT8&Xt~1}hdkt>4gYpcheGaOpA3l8e z|LBR+{}-*?@V}{N#{cBP#{ce7dH;2sBmavVdj026b@@4{QvOb{r`_1 zJpkj!pmG9QM!?DiPaDgD^-Ol;2@Ap8OBX-^9=$HB4ahZ6Wq5+Wm*{?Z9r}({lN*=Nk1tBD3;; zOW(}@>$mLuf9={eaGCJ%!96eyDjPuM0tkc31P}(5383}^s5}5+ke@+*2el1A7+e-Y z$1OqSBPiTJ7!;Nu3<_6J_`=#$uy6;{Nc}C)cp)gRK;`tvPPL=Hr!)k>V@-b%^LC)L zhKxaZ{^u`5`yNzZfzm1{-NMGdK=~e2&%rP#--Fnow)?^r8^G;yP+sR!bNtUFZ~dQH z-sV5Ef(1a( zx%2-Yf!hf8!Q}z0y?|UEfXV_``vAEtfQ1jJJOG6qq+Ng*Lj;urpm2tj1)w-UjuRLg z)J6l91EcE+D9r^UM?b920MVedgPyiPd=LiJL7?;pON*d9531|IY4y_wa2*dyzo2{$ z!k{$$$mRtpHtQOU(Y4#KRc++t_aEJp!^2Iu>6P4hl%5&(bdEG;PwHu{h$P+ zL3tPz<1!bQINW@AyTcArW+~eKXH&BMuj3f;Kdq$s|I$?({$IU%<^R2VxBuV2e-Avi z02*HawGluVGPdvpJpTCN`P2WPu>%l>wGG~b<|N_mg7@I{44|+Eg*mJo0L29;UO*U@ z|3Ng24~k1rIRJ{+k&~K7eM)KwfYJvjtzcWH21-ll`5u%GK^UIzq3wH6dlr;_@7%rj zfA-?l|3g#D|BD%T{%2OQ#oJE@4wZgt21yc*8nJ_HXM z&86=6pHtNV>=u|_5KYJ)a^yi{6C!%<|NRq+{!f^(@c-F!=l9^A$U&DDK;4_;FPs^j0iee?hElgIxT zuH5)PAgSa(sILslGsqY{pTXo{;^=&E9{}9XxBbtdYX4tU&*Q(cW#E59mze){eyRVx zBXa+TCY1b7$gKIFncwukptR$ENk!NH@~WQy6*ay8D{J~7xE4y+^nv9{E4%*}mUaBk zDro+nm|6QjJgMxzPh{SI$AGl|#;&pdRjot7K7a9IFdn+R$TfG{Y2KJACw+7>0;V1?vTgLG*+8Q~%dDP5EEnG#PAHWo`fe?827+5lLnL zor5y|>o`XK7t!JcHVKpgsXHDP&a5 za0>y@{5>e&gU0p{b9kV%0>Yp?4@x_rJP*R4d=F~lgX$Yly#vPY-~PXI_wN7JiF5vI z+K2yV0i|hBJqN1qK=m~N8dL_r#?{$X9RACj`~SD`P5vL5T>ihPyz_ru!=(Rpjg$Y^ zH%WwQzf&`eA$! z-8A)oZR3>xbxl+L*EUT04{ATeq*nfS3`qa4Y#H>QOU(%~PXH?SKo~sk04mc^F|6EU z2A6lBa>MRFvx4=1Rh!`dl`RwgpFDZ;|E-(X|KGWD6I>SDzkl~X2!qB7U}XVlE&)^y zfW`?xID(|_(cS?h9ELjyYVZI4 zgSqbxmhVyO`!Aos>+wM83)KGvrMJV!PlM;h`L$f2bMK&ZjF^81rEw4j<#7-Vsv|)( zj1TG)OBs3pxAso@ADvqHzqG37e{JI=aQ*`2=Z5BK|Islb&tl8Rm|`IP*z|zJL3V)T zkl7$UI>sdr(hrgYmrKy{prWSle_VR?e+U1x|8k~&;B^Tw{}NBz{uj`8{U4rI_J6~c z9sjRiy8Mh zs>KlOC1E8@&P+Wn^YtTAFP`eF;Vf_M7 zIRL_-cn8HlG6szcfX0A_e@+-#J_N-nsK19kt`ABBAdH;vL48Qj`V&yz2i5l=yk_&R z{}z79;CXpa-yD=aLG?Kd!}u^7l-42G_P?~T?|-+DtpE9??cnx&Beb6m>2E{Z*+^}4 zP~HONTM!MyFg}ciiKEk?_CG{yDttTu!pCI~T7Lq~9WcGv?1kljh#E|D8d|3RuWyEo zC4l-fps_^-^8oO;0c0Ko(k}poAw1la?ZI;r5I$tx6DS;wJ!1dQoWJb<)hn0&-?)DD z|BV~hzm~ zFd9R=dFp?V7)+jMx_KIkK9Ct8OpJbz8W0Axd2)-}z02Iz3K4|^{ zv?dC)Zeqr~rT?#9z6kCcfXV?#-vF|<05o@itvvuL2j0Jb2i~IyDg!_mR0e=Bs2l)c zP}%^c2?+fYdd4YaL;#eIhGz~L-o66u3&E)KfB*OoYX5;SDBpuHsC@{^`=Gkw-MhE{ zx9vXo-!>riKPcUS(jP1x;-f)*dL@g%|G{y^|I4a-|JO85hTP2av}Hz-iXt_n^C^N65zMfl1AP+X&z1E97b zC~bhs01$?y84wNX4~(_}hDJF7iYxTI4~kC^2E{R`ya%=aKo~SW1WE@_o<8|s+}Qu0 zTf+&m=LI@{2TE%ojF}#7!RzNhX*RQ<`F~~I1aKa&tef~Bge#ylhz-IpK7yVARtJ&; zVVF3GO$#nsvZ(M zYWIQC0;o;^r43LS0IDZI`5qaA(iEs(85+4@WVsSnHvj$&Iztz7jvgrPKzSa7Vfh}^ z#|OnVD9%Co9#ju3Sh4ZHjF}&#kB>BGjh^m6WdLaGk3-e*znMq;|D591|DZN(MeT(D zDpV~cn z_Wz3)&VkDTaC_j!HSqdEPswHqK>GTqYk5HBIH)`a#VH7b;uy5Y92DQ@FJ1ZX9+mr_4U~SM^*ty( zq33%TpIy}fye>AgpyhvAb>IK8ntlXb1L2oK#Y@5bzW*?O84ADeKdL-T9fX{D9&Jgqam>{yPMv{olNG$Nx*vasaf305)$3 zTSo+%D*&|xKw|@-wg9XQ0M!Y|WdNw&0M#GJ`5(jvtsx$~xnbnE3{(z-@;)d|kTEFV zgD|K)2hR76o$^W47CN=Be|A|?(|BEZT|Cdzv{x7cT zMWcIg@L}Qzy11(6KM0ppfy{xhiz|Enmw?1UbY;(fFds(4#IevNAoVbDu)9F!fXqdA zAB+!k2Ra{@I4*TC^&t0y?1S;q)uZ!a>R>cTF9^flK+!g?h4}#7;1eF7zG5}OhfZB?nv;(R?KxqlN z9QgJ7$N$l_0s~vlfM#a?{sXPwMXcik#SsXD;tZ7cL2(Ew&p~ktI(y^N)$9MA!m=>> z_~`WtC=G$?8_+p8!STiaiz>Rn`Ln39`#%hW@+gd5RM8F2vmidGi~!LnxS|W9uL7dK z5XuMBAhC)raM=Q~rx?U9@A?m>LFR(^AbBti(GOP#5(BvjW*&$Q!XSMZbPw1K2zNvH zFn7Yl!R`m^$1aah4|NO39wdyeACnI;7c36e2jj!&?*EYRgqROf2g6Y*75`;T{D_*D z0reX!d=md}-M-`hh4W|sUxtnmg4Pj%<_yu>0tO3OrDDQ*v{ijdw|AXrNY4cZt*Osz?*62gq z{OI`}#0RZS;Z$?@59)t{*6e`tXkmHhe-JJJ(_R13X^>oDIl6e~|AMj(u)e}Fh<+Gd z0OG@NIY?dSe~=tZJxCscJD}n)c`P(cKQaw=C&*lg{mABGx)a^qT@W{e%mbT)DUa@d z{QOR6c)@6xc_8;e!Uduq#)rvw{Rf2svU|bovX1}mp;`ZVHJ!ox4M62IB;HWR2S8$= zeMbD+uKyc5C;vZt<`kqYaOvXzYoK+-xY`1*UVzU|29*Jz^aH9tKxY_((iEs(0i`n# z2IYSU4Z8CXa{uXQSwQ=;2y~w{Y@81i2OtcJ2T=J8iX%{Y4T>|^7~g}3kNyXzl>Z0i zdr+Fd-F}3mAJBT$r0hCyn$0im0H;Av{sCbKzvDk{x*eS7LGt-!Aa(8kL3Cbe2b6~J zVe)yU5I%xNRfo_A6Nk_sGeH<84=SfXd>9Qg4`vUDMt46%J(~Z@(D-2ggTx>hqz9BI zL1uwyh`FGA3zY|}hw(e1;RNG@!ULoZ#z&Wj@gaVM*a1-wvjb^K4yZ~PCMcLkky zKqy{8eK?PZtpEG=?fZZJ?3w=;FP?*}C4|lsz}o^(9)Zsx0nHJ>)(?Wp08m;2)hD3z z1u6qTX$_R_AZtq??N3O50CfL4?eoA$wE}V9U2x88r2+h zedO|C_QCXn_#I$-{i5>!3+cGQ*A0Wp0uV+o=h>9)|0`Jd|6jCh)&J9{PyWAf?ksqo z;QIBe|8Ly{?LCI9C5DX)fcgWVaRKE104RNd$^Z}sr8^LYlmpOl=RZIHgX$+xIvuHb zlve%*_4gs=Ei|luL+1HFc^?!Xpn4yi_o4gpC(K^@pIg%zJjMr051=#w!Z1FVRwU84darB zi4#l1%!a9l`3FMd_BSXTKx#lVNN-L_8#oL=d=&BGw*O#09(l0-Vl@3o>cR3ze6V>~ z)wlfzxg#Z~?!Pu@4>t6i5^%g?+kXvRFHqCg|NrEPAPpH&FT$F2X7>8v6&eqqc1%)(}{8jw0< z3=s#(L2zba6Id;X&MIvF528V8;B-OL|4bML$-~$MP5;5_k@#?RIK*J;VKl@Zs5@Zh zf!*Bj%YP6JmWSzssVjt-0oM=Z zBlNfa2ib+-L)63haP=^8n0=6V0ojYJKc}emzei}+e;#!wNPABS`}$2#*#H_F3`i*W zf9TM`|L4w}0*?=Z_85ZN0?1>7puGg3c|vf1;LR)Wo)A#m5|q|J^$n=r0i{7uS_I{P zL^&{eKMA!;0Z@Ai6t>716yBin7ZeAGy#Mb1)f+eeoBJk%&zHfd=aK3I(7Jxmd3@nX zrO^Ba%A=6{0m?rapuC2bFG1`4z~Ti^bp_4feY{}td`N!I$ZrJaF-*GYKS(b~973b> z8{zVx{0`b53{i&=2aCbYZvxwmY#u}(%zkwD!1$;%NDs*U5E^18f{*YYL=5C_NH}GH z!l1DEKa2*285l#w!Rle*2T})OgD@z}pfo=9==#C#1DOLizv+Jl3LoMwkeRXRmH%Z; ze6hCsKxqPmL1h4F+)&Rs;{TSd+raaL=g*yitRsew4T9DTfz}X%$^g*XK~R4Hv{nGr zuLO+^g7y=_`U9Y}2+I2)3`?h@?EuP408qV;Jk|#aUr^o$mAjz44=RU2V>6)m*njxM zeSui-xk zgZOYdw;nDJ7KifFh@e4cAgcqh$-yvt({daBgY?7sAomjC4w!oEG|2yra6f|F3=1dF zxEnZ(@b#* zNE>_qU$|t&|C1+?1VCi~=q@x+82}m^gtY@eWdJBGVs8ih z{0~aQAWV5~7iC2Z^E6AhDEeh#ZIp%V*dA zCyUOh1=|5K2W&3XPMmC*y*YLNQ*#l10I5gjgZu=;ps)a8kUWHLfP_yjf(EP2Z9s%6 zC>)XGVftX|DCNV#HvD%D&iD_S%LVoIK=~a#J%IU2cHnbb`=`$SfBe{y z|EEu#K0H`eh8WRBZ2av}FLG=)*PQu*|0F7Ray!=b9kJ0D%k@G$%oMCzY z)5rJ!C(l{-p96fB9OP_!SUiK`7LFBd|AWrJ_KC~|r(IC}fDI>Q)q>jva5@{AU;7_f zJSiK*ulbLY&VtIr>6-sZSvCKYv!QergieC;L2^l1)nGMnIK<(F&IY*)BoFd$E!a=VV09pV9o*j_F>K*Ri5MvFQlcN9UXa6UUDHKXvl>e^7q_v}Wk~wX6R@>jv-Ny9++6 z9JY2CG&cZh2Y}k1A3s6H1#z|m{`~q6I%{;a9Y9Qp@b5pY&WF*UwiPJfgW6i4HCdo~ zAJh-4?VJj}YXa1cLy1r5dS0-&lHGq%eNXWD)}S@Kko*cs>!AD$!ikxnyjc66c)A*_ z7L*?oq4^V}7s9XppO9Gv&a=ogh>ecpGb+JqVdA9n6VUX-%t57*-2-!X&3}lyk!gq= zEIeTHFg~a}0r?TZM-4-e_+Z4K@*ygv9DF7rXl)lLoxm`tegLsyG-!=TdP&3oqlXWH z%K*sy0Az15=uA@3odux1grIf+Y+Ml34gjS^P#XX=CICvOp!5o=vq1RwAIN+as4WYs z*NDjhBUKHkd_?c>|M>asKPXJWc^`V-{+lP_-6jV2F(q`WL5k>cyRy!6UUE2#{|xU&ldo#9R`&FpuL2kG5|Ct0O||8c?+E%#L*6b z)ngzUl*U1Lq~>v4{sx5!^87xi>;#pgpu7)i?}N%#P`wW-Z&ONI;Ojk*%WqhGg7Q6R zoDZ~?FD9+xKWI!iE~5&ZFXPgy!2H+@2o1`sv1y<@S@}OEy%HjaM1#bl(<;DnG3ihm z$_I&qa7=2&|5%VcV7mN&Oj_Chm^26t%DXYC<^Lgc8JLbmOWApfWi($gYrCx2B`zn&~QZN zgTfM|4n%{(8AOBlATuERs{f#H2k8NcgXBTtDDp6K;qe2BC%Af0JVMJagg!`l1~Lm2 z&meJ-dJqlbgX{tG(<=WPI7i~#KLAQgAPj0JM5LAe-@kwF{}aa{V*;Rk#h~*C!RrL> z-UjytKxF{z&N5J60NxJx^Z|VSIPUR)(RG5zA zg>QU8BY18f5>L=`AW+uxgYKcT{jcj7@jn`#?xATOls{7|z~Z1b0Z1N{cVkjOd8qt9 zh>lII0Mnqn5|vs8RvVRC{vU=xdZJRw!2C!k4d#Q`DIoQw|D#eMI1)^k{f|s8{SRVC zrj&r?Ks1=24C0skj{?y!oKpHf62>M#gVll5gUyAS1LLPc?1Z=tb^xdhz&{=U=?j4BxzX_ePzeAU7yb7i zw6+J-HiF?FKOuMOg7QABzYnVS6ABS|A3gsg_;&w|T%#fR7Mv%`|AW#zs1Jxrm;H|d zr~5KU`cFpi!QxOph#i$&`adcOf}=rsIl1(IL`v!Zh~$$05h*1Q8YGrn@*kA9!Q#m! z|HG3Yav(Z9x%fXECl&vX0P&NGz+z!&bVOp&|A?gG|KU(N0wfROCqc!LX|Op^v%%(; zfXxKk1+^b!7pSa&xC_qD0FfuIE+AH0TxFNH&7Tu`KaLw33qTg zk^(7HK=KfN*?(Ak;N*kKTv&MovIArW78<4>l?K@j!l3dPLc{EXmE$(PN&i862S9B_ zP+mu*AIQ8hn6GH_-!Co?UIu{11tEJ0FM{_I-?@DgzLywzJOES%fW`wr?N(6x71WLe z)oF-(M}C6SJgD9S<${rlLE|ByJP!&R7!9lULE#2#^MmGGGs@er*8AXif{yor+WaQ& zvHv5$d9f6l|M1hGycw2Q3|0$bBV(92G7VybaZ>UBu*9POV0JU~h$gYqP?G)OHv4h83v;{V7rhz-Lb@r7VHa6SX&X)wR=KPX?KT9HbA)9*`akcO*jG2Xb?0e8GQ6 zxdQSB3>QKD1ffA;0`f014PxWMu<#B`M3fuIYGLw&icTu|4{8U1?q)%*M?mQbg|BG) zKQXWR|GvF@{vSPZ2)tGZ(hj%)K64aXI{;J$fcmSTb^xdz1J!4sv<<53Kp2+hL1$Qi z`T`@V900X@KxH2+96&S(gTe=t_d#I>>hFL0`0jt}ggO6N6+!n*BDKq)^*tn>K=;x@ z+Wa92MgKz*i~a{EfYN#)lrH`c5(lMa7>4CvWE#Xq$H8$0|3P9P8XFFZ%LC`_AZQ*2 z@sV+0Z0>&$9~%u4L&ia|x&H%Wa{q(qpqLym9SEXhK;k+7gFtd13{r=LLF!S=iOc&B z;)CqPz_EGYvIZm$DszHkA!QGk9ar!l?8kUec?I$}gb((AJcwTi4hs+;8H2(U#K%j6 z;w1qZFNsC}L%{I^<-^4B&@lBd8WO*_^+VLb;vcuV-~>=xsQAB?cfx532Ve`TyPjIZM~#pWg?U19t!QoFe~&;xZ_{;D1nj;eS-R2rLFl z+d;52j)R8eyG61xf2h`_B9tQ#CeNdRd@;+#+ zA5>;;+OZGoxsRYS8iYad1RA^1v_n#h5rL$3&3n-Iv_Uxe?TlKujc;`jD_HU z7!W`2KQ4F^O+{Ri@AOb*1~AUXyV zPM|hO-hWWJ2P!MDg&S6JXt)Q&fWp1tKPWChaR3hEI8eOgL*olZBgY?dd=ip}>BFWD zYHu8f#;*?4e*~o|So*?7bE-Q0@0~RL|K2^j{vSNBAKVuJtrJ2X4|s6@-hcSKz-z>L zLZEsLl+HnY0Zils0OftqJRiuZU}AT|_(*vQyBJRL0W1EnGS^#9)BY5#p9Ky>8jf%} z?>{`;L17CHe^4CY$Dp#sA7n;M{(pG$96b_(v5h(A2>izo<9{ksE z2>%bt^B@e%{~$I9L-@A;rHsA*`$Xpa_lwT^?;8b4gP1f(KIgx06evyS{`UpvSr82o z^9AXT%K7gbnGME15n2CzBQdd01Sl_M{r3)s)V)68AU8q-3!y<}6|y*l4>BJiuVC&^ zaKC_(Wx)TnYuEnYw|DpdLx&*k0MHqOpmqSL47dkfBlPsiqyL~aLT_HbL^(eIROf-x zJ}4i6&J%{^3s4<79LoSu*#`0}%%7mL59EJPSqRGeA3uHopS$Q5l?Ohb7n08r>w6G< zJMdmVkMOMj-jO-rGQc}B8_WjLK2bUU!E|KKfA0uTT7}WsNc^n--Vq=S%Eu7eJ0kPH zS9r#M7!6{>uxD60SPn#k@{JdW56Z`3Y4Cgu%6l;E0nW>*|2;w=`PU;P8O(MM2GPm? z-Gh_@*iS;3fOFr-5?BhQwXBG0P{ia z1Gyhu4yA+r0Pz#VpI%`ZaR0)>095vY*s$<{(V()?J3Q+@sO$uZL1<8zf^a6dtboJ= zDEzbj`+(vK94{a~a{R#Ji7*W+_dyt9E+h>g^C9B6%*Q2;u-7Xh>%WAd7qtBeITsR? z{@@riE}&%h-@+^Q|MqQL!1Dq}4uj?ej)KPnKxF`E&k(2#fVTr)KK~CI4+PB#fZDjA zIuBF^fbsz>Ux4xksC^6?A0JL-0LVWee}Vi5!XW>G>V8Dte-A!isi>hJJjaiy=P~m? z=#DO@z|{Yq;aOnp1*SoHH|sx$jf_3RAmXTW=6__qXIRF6kFfOrpuFu7nubAx#N0zb zc{%Mrga)xec?^=@+=F2>C|^RbTTs$}Wb7K4_}?uk@jr-m4NUlt!0}))mjIAh{C}4K z5I+G*gZOd(T?0WhNE|_f#2{us#36i``4Ae}eh?c}HlW}TsJp>5$UhK&d4l{JocbT+ zZx0YVH0{58D3p&DKA=lk0&X{~ed_mM_fz5!#A2i;=A!HD zK=}fJe}m5v93ExBzyGj3P$2)o@;<2U2bF=Kx*rrC%hzoK-wh86S6ulYG{X<>`>r|E|F) zU^a*k!mh!||J{NR*cF=3!TCBU>Ay=LB=14;bK-vx4Z_a;ki6^cANL=EWB)t*Be0Vn zf(;UP@{0k>!)TBgGKPsmXposO^O0##IRYwIKs2bFfVd6pR&aTg^xriQQBJuBCI5E? z`z-}R2dAL=KP2_PTSy8xj6gJ~EQDZCxd>dJ%2ZT6;4~iEM zhKYmNlwy!s?xCP~MolvyaTtc#0pr7HTfaoeouo>(IM)k<)(+IS_5Rl09qda zS|fbJuOtrLdL34qoHfZ70{v=7PypfUi|4glp37#b6AlK$T{I1OArgJ>8ZMuWsa*bSs67?h`> z>cMSSk-O2iYmz%@? zYA?6{89u)MgMGvPJNZJ*^NoSp1F|1tAJ`pG_kh?iw}Q$f5Qddc5I-e?{R;9Y41>Y~ z77idbI9xzw9VncFlE7sJNDLH)ps)j#nIJZThJ-aJPF#Z!;qMj<5r@PRNIdO7NZu7B z9t4t0gTym9-XLrjBsR!A7#~JM^h4Al%Y)dsFvNa@9&~lauF>HALafTRC^V>!f?Inbf1i@d|AVS3|BvXX{oiAv{eO|2+5ZN2=l{_@L0~&U_JQmMl{5Arcfl~! zt)Q|1Tqc410mdLdf&2&ZC&a%_Ab$rS!U4p01cwncd;$}}Wu!Bd28ACe93eOv9G1@T za8CITW(TGGhlM|w4oZdak!XlIOmUccba_I2m_8VdOFdjX2$F6<>Rp0U|EpRB{%29P z1@AWptuY6&L1#;V@;|t}s%ZOP+cEtA#trNL@7cZc|Ni~^z-I}8?jHlq30%8+^*?A% z0JJs$G%pA`LkKh$04f7O^WC7l0ICx~WdJDO!!RiC4CS?fpnXm-zkup~P@5lA)`8kR zpu7)i_vhAhLF;|QI14;nq2nx|`4)Tsr2mcq$zbe�H6>@{|5Mg5?o3L>|NkrRBu` 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

t0&^Q379{`yTfUF6Ci~~U007d@~ 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 MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } + + if (minFeatureLevel < D3D_FEATURE_LEVEL_11_0) + { + throw std::out_of_range("minFeatureLevel too low"); + } +} + +// Destructor for DeviceResources. +DX::DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ +#if defined(_DEBUG) + // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + { + ComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) + { + debugController->EnableDebugLayer(); + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } + + ComPtr dxgiInfoQueue; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) + { + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); + } + } +#endif + + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); + + ComPtr adapter; + GetAdapter(adapter.GetAddressOf()); + + // Create the DX12 API device object. + DX::ThrowIfFailed(D3D12CreateDevice( + adapter.Get(), + m_d3dMinFeatureLevel, + IID_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + +#ifndef NDEBUG + // Configure debug device (if active). + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D12_MESSAGE_ID hide[] = + { + D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, + D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + }; + D3D12_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + // Determine maximum supported feature level for this device + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + }; + + D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = + { + _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + }; + + HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); + if (SUCCEEDED(hr)) + { + m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel; + } + else + { + m_d3dFeatureLevel = m_d3dMinFeatureLevel; + } + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + DX::ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // Create a swap chain for the window. + ComPtr swapChain; + DX::ThrowIfFailed(m_dxgiFactory->CreateSwapChainForCoreWindow( + m_commandQueue.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&m_swapChain)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size. +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc.left == m_outputSize.left + && newRc.top == m_outputSize.top + && newRc.right == m_outputSize.right + && newRc.bottom == m_outputSize.bottom + && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + WaitForGpu(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_commandAllocators[n].Reset(); + m_renderTargets[n].Reset(); + } + + m_depthStencil.Reset(); + m_commandQueue.Reset(); + m_commandList.Reset(); + m_fence.Reset(); + m_rtvDescriptorHeap.Reset(); + m_dsvDescriptorHeap.Reset(); + m_swapChain.Reset(); + m_d3dDevice.Reset(); + m_dxgiFactory.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Prepare the command list and render target for rendering. +void DX::DeviceResources::Prepare() +{ + // Reset command list and allocator. + DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + + // Send the command list off to the GPU for processing. + DX::ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present(1, 0); + + // If the device was reset we must completely reinitialize the renderer. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + + MoveToNextFrame(); + } +} + +// Wait for pending GPU work to complete. +void DX::DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DX::DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + +// This method acquires the first available hardware adapter that supports Direct3D 12. +// If no such adapter can be found, try WARP. Otherwise throw an exception. +void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + DX::ThrowIfFailed(adapter->GetDesc1(&desc)); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), m_d3dMinFeatureLevel, _uuidof(ID3D12Device), nullptr))) + { +#ifdef _DEBUG + wchar_t buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + break; + } + } + +#if !defined(NDEBUG) + if (!adapter) + { + // Try WARP12 instead + if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) + { + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + } + + OutputDebugStringA("Direct3D Adapter - WARP12\n"); + } +#endif + + if (!adapter) + { + throw std::exception("No Direct3D 12 device found"); + } + + *ppAdapter = adapter.Detach(); +} diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h new file mode 100644 index 00000000..086d0cec --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DeviceResources.h @@ -0,0 +1,117 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Prepare(); + void Present(); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + void GetAdapter(IDXGIAdapter1** ppAdapter); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_dxgiFactory; + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + DXGI_MODE_ROTATION m_rotation; + RECT m_outputSize; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp new file mode 100644 index 00000000..9e9f7788 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.cpp @@ -0,0 +1,500 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample12.h" + +using namespace DirectX; +using namespace DirectX::SimpleMath; + +using Microsoft::WRL::ComPtr; + +Sample::Sample() +{ + m_deviceResources = std::make_unique(); + m_deviceResources->RegisterDeviceNotify(this); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_mouse = std::make_unique(); + m_mouse->SetWindow(reinterpret_cast(window)); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + + // Create DirectXTK for Audio objects + AUDIO_ENGINE_FLAGS eflags = AudioEngine_Default; +#ifdef _DEBUG + eflags = eflags | AudioEngine_Debug; +#endif + + m_audEngine = std::make_unique(eflags); + + m_audioEvent = 0; + m_audioTimerAcc = 10.f; + m_retryDefault = false; + + m_waveBank = std::make_unique(m_audEngine.get(), L"adpcmdroid.xwb"); + m_soundEffect = std::make_unique(m_audEngine.get(), L"MusicMono_adpcm.wav"); + m_effect1 = m_soundEffect->CreateInstance(); + m_effect2 = m_waveBank->CreateInstance(10); + + m_effect1->Play(true); + m_effect2->Play(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + // Only update audio engine once per frame + if (!m_audEngine->IsCriticalError() && m_audEngine->Update()) + { + // Setup a retry in 1 second + m_audioTimerAcc = 1.f; + m_retryDefault = true; + } + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + Vector3 eye(0.0f, 0.7f, 1.5f); + Vector3 at(0.0f, -0.1f, 0.0f); + + m_view = Matrix::CreateLookAt(eye, at, Vector3::UnitY); + + m_world = Matrix::CreateRotationY(float(timer.GetTotalSeconds() * XM_PIDIV4)); + + m_lineEffect->SetView(m_view); + m_lineEffect->SetWorld(Matrix::Identity); + + m_shapeEffect->SetView(m_view); + + m_audioTimerAcc -= (float)timer.GetElapsedSeconds(); + if (m_audioTimerAcc < 0) + { + if (m_retryDefault) + { + m_retryDefault = false; + if (m_audEngine->Reset()) + { + // Restart looping audio + m_effect1->Play(true); + } + } + else + { + m_audioTimerAcc = 4.f; + + m_waveBank->Play(m_audioEvent++); + + if (m_audioEvent >= 11) + m_audioEvent = 0; + } + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + auto mouse = m_mouse->GetState(); + mouse; + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Draw procedurally generated dynamic grid + const XMVECTORF32 xaxis = { 20.f, 0.f, 0.f }; + const XMVECTORF32 yaxis = { 0.f, 0.f, 20.f }; + DrawGrid(xaxis, yaxis, g_XMZero, 20, 20, Colors::Gray); + + // Set the descriptor heaps + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; + commandList->SetDescriptorHeaps(1, heaps); + + // Draw sprite + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw sprite"); + m_sprites->Begin(commandList); + m_sprites->Draw(m_resourceDescriptors->GetGpuHandle(Descriptors::WindowsLogo), GetTextureSize(m_texture2.Get()), + XMFLOAT2(10, 75)); + + m_font->DrawString(m_sprites.get(), L"DirectXTK Simple Sample", XMFLOAT2(100, 10), Colors::Yellow); + m_sprites->End(); + PIXEndEvent(commandList); + + // Draw 3D object + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw teapot"); + XMMATRIX local = m_world * Matrix::CreateTranslation(-2.f, -2.f, -4.f); + m_shapeEffect->SetWorld(local); + m_shapeEffect->Apply(commandList); + m_shape->Draw(commandList); + PIXEndEvent(commandList); + + // Draw model + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw model"); + const XMVECTORF32 scale = { 0.01f, 0.01f, 0.01f }; + const XMVECTORF32 translate = { 3.f, -2.f, -4.f }; + XMVECTOR rotate = Quaternion::CreateFromYawPitchRoll(XM_PI / 2.f, 0.f, -XM_PI / 2.f); + local = m_world * XMMatrixTransformation(g_XMZero, Quaternion::Identity, scale, g_XMZero, rotate, translate); + Model::UpdateEffectMatrices(m_modelEffects, local, m_view, m_projection); + heaps[0] = m_modelResources->DescriptorHeap(); + commandList->SetDescriptorHeaps(1, heaps); + m_model->Draw(commandList, m_modelEffects.begin()); + PIXEndEvent(commandList); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(m_deviceResources->GetCommandQueue()); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + commandList->ClearRenderTargetView(rtvDescriptor, Colors::CornflowerBlue, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} + +void XM_CALLCONV Sample::DrawGrid(FXMVECTOR xAxis, FXMVECTOR yAxis, FXMVECTOR origin, size_t xdivs, size_t ydivs, GXMVECTOR color) +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Draw grid"); + + m_lineEffect->Apply(commandList); + + m_batch->Begin(commandList); + + xdivs = std::max(1, xdivs); + ydivs = std::max(1, ydivs); + + for (size_t i = 0; i <= xdivs; ++i) + { + float fPercent = float(i) / float(xdivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(xAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, yAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, yAxis), color); + m_batch->DrawLine(v1, v2); + } + + for (size_t i = 0; i <= ydivs; i++) + { + float fPercent = float(i) / float(ydivs); + fPercent = (fPercent * 2.0f) - 1.0f; + XMVECTOR vScale = XMVectorScale(yAxis, fPercent); + vScale = XMVectorAdd(vScale, origin); + + VertexPositionColor v1(XMVectorSubtract(vScale, xAxis), color); + VertexPositionColor v2(XMVectorAdd(vScale, xAxis), color); + m_batch->DrawLine(v1, v2); + } + + m_batch->End(); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ + m_audEngine->Suspend(); +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); + m_audEngine->Resume(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +void Sample::NewAudioDevice() +{ + if (m_audEngine && !m_audEngine->IsAudioDevicePresent()) + { + // Setup a retry in 1 second + m_audioTimerAcc = 1.f; + m_retryDefault = true; + } +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + m_resourceDescriptors = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + Descriptors::Count); + + m_batch = std::make_unique>(device); + + m_shape = GeometricPrimitive::CreateTeapot(4.f, 8); + + // SDKMESH has to use clockwise winding with right-handed coordinates, so textures are flipped in U + m_model = Model::CreateFromSDKMESH(L"tiny.sdkmesh"); + + { + ResourceUploadBatch resourceUpload(device); + + resourceUpload.Begin(); + + DX::ThrowIfFailed( + CreateDDSTextureFromFile(device, resourceUpload, L"assets\\seafloor.dds", m_texture1.ReleaseAndGetAddressOf()) + ); + + CreateShaderResourceView(device, m_texture1.Get(), m_resourceDescriptors->GetCpuHandle(Descriptors::SeaFloor)); + + DX::ThrowIfFailed( + CreateDDSTextureFromFile(device, resourceUpload, L"assets\\windowslogo.dds", m_texture2.ReleaseAndGetAddressOf()) + ); + + CreateShaderResourceView(device, m_texture2.Get(), m_resourceDescriptors->GetCpuHandle(Descriptors::WindowsLogo)); + + RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(), m_deviceResources->GetDepthBufferFormat()); + + { + EffectPipelineStateDescription pd( + &VertexPositionColor::InputLayout, + &CommonStates::Opaque, + &CommonStates::DepthNone, + &CommonStates::CullNone, + &rtState, + D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE); + + m_lineEffect = std::make_unique(device, EffectFlags::VertexColor, pd); + } + + { + EffectPipelineStateDescription pd( + &GeometricPrimitive::VertexType::InputLayout, + &CommonStates::Opaque, + &CommonStates::DepthDefault, + &CommonStates::CullNone, + &rtState); + + m_shapeEffect = std::make_unique(device, EffectFlags::PerPixelLighting | EffectFlags::Texture, pd); + m_shapeEffect->EnableDefaultLighting(); + m_shapeEffect->SetTexture(m_resourceDescriptors->GetGpuHandle(Descriptors::SeaFloor)); + } + + { + SpriteBatchPipelineStateDescription pd(&rtState); + + m_sprites = std::make_unique(device, resourceUpload, &pd); + } + + m_modelResources = m_model->LoadTextures(device, resourceUpload, L"Assets\\Cathedral"); + + { + EffectPipelineStateDescription psd( + &VertexPositionNormalColorTexture::InputLayout, + &CommonStates::Opaque, + &CommonStates::DepthDefault, + &CommonStates::CullNone, + &rtState); + + m_modelEffects = m_model->CreateEffects(psd, m_modelResources->DescriptorHeap(), 0); + } + + m_font = std::make_unique(device, resourceUpload, + L"SegoeUI_18.spritefont", + m_resourceDescriptors->GetCpuHandle(Descriptors::SegoeFont), + m_resourceDescriptors->GetGpuHandle(Descriptors::SegoeFont)); + + // Upload the resources to the GPU. + auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue()); + + // Wait for the command list to finish executing + m_deviceResources->WaitForGpu(); + + // Wait for the upload thread to terminate + uploadResourcesFinished.wait(); + } +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + float aspectRatio = float(size.right) / float(size.bottom); + float fovAngleY = 70.0f * XM_PI / 180.0f; + + // This is a simple example of change that can be made when the app is in + // portrait or snapped view. + if (aspectRatio < 1.0f) + { + fovAngleY *= 2.0f; + } + + // Note that the OrientationTransform3D matrix is post-multiplied here + // in order to correctly orient the scene to match the display orientation. + // This post-multiplication step is required for any draw calls that are + // made to the swap chain render target. For draw calls to other targets, + // this transform should not be applied. + + // This sample makes use of a right-handed coordinate system using row-major matrices. + Matrix perspectiveMatrix = Matrix::CreatePerspectiveFieldOfView( + fovAngleY, + aspectRatio, + 0.01f, + 100.0f + ); + + Matrix orientationMatrix = m_deviceResources->GetOrientationTransform3D(); + + m_projection = perspectiveMatrix * orientationMatrix; + + m_lineEffect->SetProjection(m_projection); + m_shapeEffect->SetProjection(m_projection); + + auto viewport = m_deviceResources->GetScreenViewport(); + m_sprites->SetViewport(viewport); + + m_sprites->SetRotation(m_deviceResources->GetRotation()); +} + +void Sample::OnDeviceLost() +{ + m_texture1.Reset(); + m_texture2.Reset(); + + m_font.reset(); + m_batch.reset(); + m_shape.reset(); + m_model.reset(); + m_lineEffect.reset(); + m_shapeEffect.reset(); + m_modelEffects.clear(); + m_modelResources.reset(); + m_sprites.reset(); + m_resourceDescriptors.reset(); + m_graphicsMemory.reset(); +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.h new file mode 100644 index 00000000..6e25d69b --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.h @@ -0,0 +1,110 @@ +//-------------------------------------------------------------------------------------- +// DirectXTKSimpleSample12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void NewAudioDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + void XM_CALLCONV DrawGrid(DirectX::FXMVECTOR xAxis, DirectX::FXMVECTOR yAxis, DirectX::FXMVECTOR origin, size_t xdivs, size_t ydivs, DirectX::GXMVECTOR color); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + std::unique_ptr m_mouse; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + std::unique_ptr m_resourceDescriptors; + std::unique_ptr m_lineEffect; + std::unique_ptr> m_batch; + std::unique_ptr m_shapeEffect; + std::unique_ptr m_model; + std::vector> m_modelEffects; + std::unique_ptr m_modelResources; + std::unique_ptr m_shape; + std::unique_ptr m_sprites; + std::unique_ptr m_font; + + std::unique_ptr m_audEngine; + std::unique_ptr m_waveBank; + std::unique_ptr m_soundEffect; + std::unique_ptr m_effect1; + std::unique_ptr m_effect2; + + Microsoft::WRL::ComPtr m_texture1; + Microsoft::WRL::ComPtr m_texture2; + + uint32_t m_audioEvent; + float m_audioTimerAcc; + + bool m_retryDefault; + + DirectX::SimpleMath::Matrix m_world; + DirectX::SimpleMath::Matrix m_view; + DirectX::SimpleMath::Matrix m_projection; + + // Descriptors + enum Descriptors + { + WindowsLogo, + SeaFloor, + SegoeFont, + Count = 256 + }; +}; \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.sln b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.sln new file mode 100644 index 00000000..22f4a414 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTKSimpleSample12", "DirectXTKSimpleSample12.vcxproj", "{CE7FAEDA-7DD4-451D-814F-EC053C536DF3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|ARM.ActiveCfg = Debug|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|ARM.Build.0 = Debug|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|ARM.Deploy.0 = Debug|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x64.ActiveCfg = Debug|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x64.Build.0 = Debug|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x64.Deploy.0 = Debug|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x86.ActiveCfg = Debug|Win32 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x86.Build.0 = Debug|Win32 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Debug|x86.Deploy.0 = Debug|Win32 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|ARM.ActiveCfg = Release|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|ARM.Build.0 = Release|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|ARM.Deploy.0 = Release|ARM + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x64.ActiveCfg = Release|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x64.Build.0 = Release|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x64.Deploy.0 = Release|x64 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x86.ActiveCfg = Release|Win32 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x86.Build.0 = Release|Win32 + {CE7FAEDA-7DD4-451D-814F-EC053C536DF3}.Release|x86.Deploy.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj new file mode 100644 index 00000000..0383f837 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj @@ -0,0 +1,288 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {ce7faeda-7dd4-451d-814f-ec053c536df3} + DirectXApp + DirectXTKSimpleSample12 + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + DirectXTKSimpleSample12_TemporaryKey.pfx + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj.filters b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj.filters new file mode 100644 index 00000000..1d7bbf95 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + 1c08aa7a-3171-48ca-91ed-430fcd59db0b + + + 4573178e-7ad6-400a-b813-912afa4bc70d + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + + + + + Common + + + Common + + + Common + + + + + + + + Common + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + Assets + + + + Assets + + + Assets + + + + + Assets + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12_TemporaryKey.pfx b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/DirectXTKSimpleSample12_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..0f74dba48f8d007a4ccdc88cc22b66155a3eb8fc GIT binary patch literal 2452 zcmXqL;+(+5$ZXKW>BGjU)#lOmotKfFaX}NOElU%pr9l&?sX-I#FBB=(*DOt}&kdSb z9~(5W-e=>6>f+&IWLnU~^3R}&<(GjB8y8HNk=cNcg@fmv>u;C7AU7r^_6sacEH|QB zpDb_?Tb@=m)4qQ8y&0=l7Qbfi63f5yul*PL@9Yw_=q}sU@tx^^cV1nQS+(G#^!H-Ewf+}hY@B1newnXR zH^VKwg>?4B;4(yvmm zxpU3cnnk)vG2T@#uAO93Q#q5}DY#OUW$B8l9?mP<^p?%vurfVp}iGZQCwv zA}=9hophN=kwxI-k|n{>9nY58KWjc{(tcmt-9bx@EyK!A_K}J@pZ-SI|FfATPwr*e zs=o5@3;hVziBA|(O*7Am>dKTonj||r^FYi>mxE#kX^g4&vU4AooqXaK`%<-m{dT6u z|Bl0pjB6y!L@(T2eJuUQzQskl!Ixwf8*G2MO>D-#2`(ojt}(1`w>6s+U%OdZ70Grdm#3+{ySc|@s?chW)&t+x>E0Ie z<38>dQ^L}CXJhMuO;_|vmWXn0K{x$2~o0`RkQSP@>5*_ZaFK^KlhSniAa|6#&05&nY@`?vp0;^a#+6XWZ#oN6I{!{o)ps-6{vC$oP{ zpT6is{dxz_4IksQ^~4{GI*J+g|;kT;ICrk6>ca$8F0euG-M~n0xufrG+sk-l}=9p4l?f;zp6*McZSWnNK~E;PXs= z-<5MV)tAL>we*vPYxFi3FFms{&fts68)M0R{o$?CEA2hJ%Y>5TBz}D?`CKS^a4u(x z*wz(I6$fOKI#iC$womB#z0Y=|*7|csz6}R5>=Kd^Q-#0JsLo9b_u)%f`slW5J9BLK z72B+@3&OIwZcCbQWz{5Oc_iWEE#ke3>nfG zj2V&{bQw$-Qo%f31`9AWV$fwsVK8Q}WH15C88ak;^(HZx8^p44YO^u2FgBSBG8zWR z`7!u1WHKZ(6fxv86f@*Aq%o8*C@=&wlz>I@7}6OO7@Qf37%CYG7)luO8PXYw7!nx@ z7&5@R6c_@)>dF{08B!Qh8Hx;=n2q5s2UQHrDlARR3ID+kIQ#`kK3O#;DuYl z$j!=NAZW;Mz{|!Q%EBznmYh+VoLz1pC(dhVW?*JyZe(O+Xkr*8&TD9HU}j`tU;^f1 z)6&GKglsS)D+6;ABR_*d6C)Q>6C)$T_1!N$zm&2l$N!cSPM=hswP=RUQl;A91dDBM zY0BZg53RHQoRj?V#!~Io$L%YMS3lWx;q$$eQyNb;ES{stlCk^N`yZTL6W9AasXp}L zMVpy))!7G&_-0<%AN(nGzjV?Zw~g12&-2dbUVk9PvShASaN_<&jZ@?ej-1$ZX?4|x zo=lgLCV|Fslg{QP3JSu7_v81WB>Wz(6M85tNCYZ#~*@USt5$_g_w z{%2t_U@#B^@l-)P9s@2m4sA9@R#tXqX5_Hs28SghL+aECKkf-Fl-ze<`h#+r2VU&! zPJQuUw3e=YBcI1Nt+yylAjsLTl-bbPr+UlOq*sPUvfX_q5g}$)2MV3f@aMd6Gw1)i z(&E|iWlD1{x$J(>wZ=g6`sIw<{cD#k;k=Oc`m?eL$3+Rt<55deZiO=OmVa}? zyrc!W{W1!%3ho{Nr-~MbklJV%h_U@JX&%#bTQhQo> z*@#hbii1gdUh5ua4tdv)`}0nfZmjo^zva)T$ofU6Pxf-Flwxd={F6O<7%U&eH?4ge zVscf_>cYkS-zQmVo~yoI#M330!JuhlQ_7qjSGxPK^4nA&^QBWPo*0T^&+gU+@&@c| ztlE6cOj0Z&O>4a-y(&L^)##AWC6CK@Hg4fr%f})zJ?#AJ_ur*cZk+zvT$O+0VbYrC ICqV5Z03~JdQvd(} literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp new file mode 100644 index 00000000..92b4e0d5 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Main.cpp @@ -0,0 +1,382 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "DirectXTKSimpleSample12.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace Windows::Devices::Enumeration; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + + m_audioWatcher = DeviceInformation::CreateWatcher(DeviceClass::AudioRender); + + m_audioWatcher->Added += ref new TypedEventHandler(this, &ViewProvider::OnAudioDeviceAdded); + m_audioWatcher->Updated += ref new TypedEventHandler(this, &ViewProvider::OnAudioDeviceUpdated); + + m_audioWatcher->Start(); + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + HandleWindowSizeChanged(); + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + m_sample->OnActivated(); + else + m_sample->OnDeactivated(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + + void OnAudioDeviceAdded(Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformation^ args) + { + m_sample->NewAudioDevice(); + } + + void OnAudioDeviceUpdated(Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformationUpdate^ args) + { + m_sample->NewAudioDevice(); + } + +private: + bool m_exit; + bool m_visible; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + Windows::Devices::Enumeration::DeviceWatcher^ m_audioWatcher; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + if (!XMVerifyCPUSupport()) + { + throw std::exception("XMVerifyCPUSupport"); + } + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Package.appxmanifest b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Package.appxmanifest new file mode 100644 index 00000000..5883de9b --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + DirectXTKSimpleSample12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..5ac43e6b0b615989e29526ac6fc380198155f566 GIT binary patch literal 200483 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

rTz>lD00lLieBFRQuJduDG(UQZB^8Qm*#P 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

e#Zg8E2LTU#(J? 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/StepTimer.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/StepTimer.h new file mode 100644 index 00000000..e6f7acf5 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/d3dx12.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/d3dx12.h new file mode 100644 index 00000000..351914d3 --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/d3dx12.h @@ -0,0 +1,1534 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#ifndef __D3DX12_H__ +#define __D3DX12_H__ + +#include "d3d12.h" + +#if defined( __cplusplus ) + +struct CD3DX12_DEFAULT {}; +extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT; + +//------------------------------------------------------------------------------------------------ +inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ + return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width && + l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth; +} + +//------------------------------------------------------------------------------------------------ +inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RECT : public D3D12_RECT +{ + CD3DX12_RECT() + {} + explicit CD3DX12_RECT( const D3D12_RECT& o ) : + D3D12_RECT( o ) + {} + explicit CD3DX12_RECT( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + right = Right; + bottom = Bottom; + } + ~CD3DX12_RECT() {} + operator const D3D12_RECT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BOX : public D3D12_BOX +{ + CD3DX12_BOX() + {} + explicit CD3DX12_BOX( const D3D12_BOX& o ) : + D3D12_BOX( o ) + {} + explicit CD3DX12_BOX( + LONG Left, + LONG Right ) + { + left = Left; + top = 0; + front = 0; + right = Right; + bottom = 1; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + front = 0; + right = Right; + bottom = Bottom; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Front, + LONG Right, + LONG Bottom, + LONG Back ) + { + left = Left; + top = Top; + front = Front; + right = Right; + bottom = Bottom; + back = Back; + } + ~CD3DX12_BOX() {} + operator const D3D12_BOX&() const { return *this; } +}; +inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r ) +{ + return l.left == r.left && l.top == r.top && l.front == r.front && + l.right == r.right && l.bottom == r.bottom && l.back == r.back; +} +inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC +{ + CD3DX12_DEPTH_STENCIL_DESC() + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) : + D3D12_DEPTH_STENCIL_DESC( o ) + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) + { + DepthEnable = TRUE; + DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + DepthFunc = D3D12_COMPARISON_FUNC_LESS; + StencilEnable = FALSE; + StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = + { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS }; + FrontFace = defaultStencilOp; + BackFace = defaultStencilOp; + } + explicit CD3DX12_DEPTH_STENCIL_DESC( + BOOL depthEnable, + D3D12_DEPTH_WRITE_MASK depthWriteMask, + D3D12_COMPARISON_FUNC depthFunc, + BOOL stencilEnable, + UINT8 stencilReadMask, + UINT8 stencilWriteMask, + D3D12_STENCIL_OP frontStencilFailOp, + D3D12_STENCIL_OP frontStencilDepthFailOp, + D3D12_STENCIL_OP frontStencilPassOp, + D3D12_COMPARISON_FUNC frontStencilFunc, + D3D12_STENCIL_OP backStencilFailOp, + D3D12_STENCIL_OP backStencilDepthFailOp, + D3D12_STENCIL_OP backStencilPassOp, + D3D12_COMPARISON_FUNC backStencilFunc ) + { + DepthEnable = depthEnable; + DepthWriteMask = depthWriteMask; + DepthFunc = depthFunc; + StencilEnable = stencilEnable; + StencilReadMask = stencilReadMask; + StencilWriteMask = stencilWriteMask; + FrontFace.StencilFailOp = frontStencilFailOp; + FrontFace.StencilDepthFailOp = frontStencilDepthFailOp; + FrontFace.StencilPassOp = frontStencilPassOp; + FrontFace.StencilFunc = frontStencilFunc; + BackFace.StencilFailOp = backStencilFailOp; + BackFace.StencilDepthFailOp = backStencilDepthFailOp; + BackFace.StencilPassOp = backStencilPassOp; + BackFace.StencilFunc = backStencilFunc; + } + ~CD3DX12_DEPTH_STENCIL_DESC() {} + operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC +{ + CD3DX12_BLEND_DESC() + {} + explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) : + D3D12_BLEND_DESC( o ) + {} + explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) + { + AlphaToCoverageEnable = FALSE; + IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + RenderTarget[ i ] = defaultRenderTargetBlendDesc; + } + ~CD3DX12_BLEND_DESC() {} + operator const D3D12_BLEND_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC +{ + CD3DX12_RASTERIZER_DESC() + {} + explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) : + D3D12_RASTERIZER_DESC( o ) + {} + explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + MultisampleEnable = FALSE; + AntialiasedLineEnable = FALSE; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + INT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + BOOL multisampleEnable, + BOOL antialiasedLineEnable, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + MultisampleEnable = multisampleEnable; + AntialiasedLineEnable = antialiasedLineEnable; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + ~CD3DX12_RASTERIZER_DESC() {} + operator const D3D12_RASTERIZER_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO +{ + CD3DX12_RESOURCE_ALLOCATION_INFO() + {} + explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) : + D3D12_RESOURCE_ALLOCATION_INFO( o ) + {} + CD3DX12_RESOURCE_ALLOCATION_INFO( + UINT64 size, + UINT64 alignment ) + { + SizeInBytes = size; + Alignment = alignment; + } + operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES +{ + CD3DX12_HEAP_PROPERTIES() + {} + explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) : + D3D12_HEAP_PROPERTIES(o) + {} + CD3DX12_HEAP_PROPERTIES( + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = D3D12_HEAP_TYPE_CUSTOM; + CPUPageProperty = cpuPageProperty; + MemoryPoolPreference = memoryPoolPreference; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + explicit CD3DX12_HEAP_PROPERTIES( + D3D12_HEAP_TYPE type, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = type; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + operator const D3D12_HEAP_PROPERTIES&() const { return *this; } + bool IsCPUAccessible() const + { + return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM && + (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); + } +}; +inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ + return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && + l.MemoryPoolPreference == r.MemoryPoolPreference && + l.CreationNodeMask == r.CreationNodeMask && + l.VisibleNodeMask == r.VisibleNodeMask; +} +inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC +{ + CD3DX12_HEAP_DESC() + {} + explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) : + D3D12_HEAP_DESC(o) + {} + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_PROPERTIES properties, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = properties; + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_TYPE type, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_PROPERTIES properties, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = properties; + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_TYPE type, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + operator const D3D12_HEAP_DESC&() const { return *this; } + bool IsCPUAccessible() const + { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); } +}; +inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ + return l.SizeInBytes == r.SizeInBytes && + l.Properties == r.Properties && + l.Alignment == r.Alignment && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE +{ + CD3DX12_CLEAR_VALUE() + {} + explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) : + D3D12_CLEAR_VALUE(o) + {} + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + const FLOAT color[4] ) + { + Format = format; + memcpy( Color, color, sizeof( Color ) ); + } + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + FLOAT depth, + UINT8 stencil ) + { + Format = format; + /* Use memcpy to preserve NAN values */ + memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) ); + DepthStencil.Stencil = stencil; + } + operator const D3D12_CLEAR_VALUE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RANGE : public D3D12_RANGE +{ + CD3DX12_RANGE() + {} + explicit CD3DX12_RANGE(const D3D12_RANGE &o) : + D3D12_RANGE(o) + {} + CD3DX12_RANGE( + SIZE_T begin, + SIZE_T end ) + { + Begin = begin; + End = end; + } + operator const D3D12_RANGE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE +{ + CD3DX12_SHADER_BYTECODE() + {} + explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) : + D3D12_SHADER_BYTECODE(o) + {} + CD3DX12_SHADER_BYTECODE( + ID3DBlob* pShaderBlob ) + { + pShaderBytecode = pShaderBlob->GetBufferPointer(); + BytecodeLength = pShaderBlob->GetBufferSize(); + } + CD3DX12_SHADER_BYTECODE( + void* _pShaderBytecode, + SIZE_T bytecodeLength ) + { + pShaderBytecode = _pShaderBytecode; + BytecodeLength = bytecodeLength; + } + operator const D3D12_SHADER_BYTECODE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE +{ + CD3DX12_TILED_RESOURCE_COORDINATE() + {} + explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) : + D3D12_TILED_RESOURCE_COORDINATE(o) + {} + CD3DX12_TILED_RESOURCE_COORDINATE( + UINT x, + UINT y, + UINT z, + UINT subresource ) + { + X = x; + Y = y; + Z = z; + Subresource = subresource; + } + operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE +{ + CD3DX12_TILE_REGION_SIZE() + {} + explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) : + D3D12_TILE_REGION_SIZE(o) + {} + CD3DX12_TILE_REGION_SIZE( + UINT numTiles, + BOOL useBox, + UINT width, + UINT16 height, + UINT16 depth ) + { + NumTiles = numTiles; + UseBox = useBox; + Width = width; + Height = height; + Depth = depth; + } + operator const D3D12_TILE_REGION_SIZE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING +{ + CD3DX12_SUBRESOURCE_TILING() + {} + explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) : + D3D12_SUBRESOURCE_TILING(o) + {} + CD3DX12_SUBRESOURCE_TILING( + UINT widthInTiles, + UINT16 heightInTiles, + UINT16 depthInTiles, + UINT startTileIndexInOverallResource ) + { + WidthInTiles = widthInTiles; + HeightInTiles = heightInTiles; + DepthInTiles = depthInTiles; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_SUBRESOURCE_TILING&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE +{ + CD3DX12_TILE_SHAPE() + {} + explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) : + D3D12_TILE_SHAPE(o) + {} + CD3DX12_TILE_SHAPE( + UINT widthInTexels, + UINT heightInTexels, + UINT depthInTexels ) + { + WidthInTexels = widthInTexels; + HeightInTexels = heightInTexels; + DepthInTexels = depthInTexels; + } + operator const D3D12_TILE_SHAPE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER +{ + CD3DX12_RESOURCE_BARRIER() + {} + explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) : + D3D12_RESOURCE_BARRIER(o) + {} + static inline CD3DX12_RESOURCE_BARRIER Transition( + _In_ ID3D12Resource* pResource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + result.Flags = flags; + barrier.Transition.pResource = pResource; + barrier.Transition.StateBefore = stateBefore; + barrier.Transition.StateAfter = stateAfter; + barrier.Transition.Subresource = subresource; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER Aliasing( + _In_ ID3D12Resource* pResourceBefore, + _In_ ID3D12Resource* pResourceAfter) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = pResourceBefore; + barrier.Aliasing.pResourceAfter = pResourceAfter; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER UAV( + _In_ ID3D12Resource* pResource) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = pResource; + return result; + } + operator const D3D12_RESOURCE_BARRIER&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO +{ + CD3DX12_PACKED_MIP_INFO() + {} + explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) : + D3D12_PACKED_MIP_INFO(o) + {} + CD3DX12_PACKED_MIP_INFO( + UINT8 numStandardMips, + UINT8 numPackedMips, + UINT numTilesForPackedMips, + UINT startTileIndexInOverallResource ) + { + NumStandardMips = numStandardMips; + NumPackedMips = numPackedMips; + NumTilesForPackedMips = numTilesForPackedMips; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_PACKED_MIP_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT +{ + CD3DX12_SUBRESOURCE_FOOTPRINT() + {} + explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) : + D3D12_SUBRESOURCE_FOOTPRINT(o) + {} + CD3DX12_SUBRESOURCE_FOOTPRINT( + DXGI_FORMAT format, + UINT width, + UINT height, + UINT depth, + UINT rowPitch ) + { + Format = format; + Width = width; + Height = height; + Depth = depth; + RowPitch = rowPitch; + } + explicit CD3DX12_SUBRESOURCE_FOOTPRINT( + const D3D12_RESOURCE_DESC& resDesc, + UINT rowPitch ) + { + Format = resDesc.Format; + Width = UINT( resDesc.Width ); + Height = resDesc.Height; + Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1); + RowPitch = rowPitch; + } + operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION +{ + CD3DX12_TEXTURE_COPY_LOCATION() + {} + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + SubresourceIndex = Sub; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE +{ + CD3DX12_DESCRIPTOR_RANGE() { } + explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) : + D3D12_DESCRIPTOR_RANGE(o) + {} + CD3DX12_DESCRIPTOR_RANGE( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) : + D3D12_ROOT_DESCRIPTOR_TABLE(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS +{ + CD3DX12_ROOT_CONSTANTS() {} + explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) : + D3D12_ROOT_CONSTANTS(o) + {} + CD3DX12_ROOT_CONSTANTS( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(num32BitValues, shaderRegister, registerSpace); + } + + inline void Init( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, num32BitValues, shaderRegister, registerSpace); + } + + static inline void Init( + _Out_ D3D12_ROOT_CONSTANTS &rootConstants, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + rootConstants.Num32BitValues = num32BitValues; + rootConstants.ShaderRegister = shaderRegister; + rootConstants.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR +{ + CD3DX12_ROOT_DESCRIPTOR() {} + explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) : + D3D12_ROOT_DESCRIPTOR(o) + {} + CD3DX12_ROOT_DESCRIPTOR( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(shaderRegister, registerSpace); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, shaderRegister, registerSpace); + } + + static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER +{ + CD3DX12_ROOT_PARAMETER() {} + explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) : + D3D12_ROOT_PARAMETER(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace); + } + + static inline void InitAsConstantBufferView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility); + } + + inline void InitAsConstants( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility); + } + + inline void InitAsConstantBufferView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC +{ + CD3DX12_STATIC_SAMPLER_DESC() {} + explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) : + D3D12_STATIC_SAMPLER_DESC(o) + {} + CD3DX12_STATIC_SAMPLER_DESC( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC +{ + CD3DX12_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) : + D3D12_ROOT_SIGNATURE_DESC(o) + {} + CD3DX12_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + desc.NumParameters = numParameters; + desc.pParameters = _pParameters; + desc.NumStaticSamplers = numStaticSamplers; + desc.pStaticSamplers = _pStaticSamplers; + desc.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) : + D3D12_CPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE +{ + CD3DX12_GPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) : + D3D12_GPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + + + diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.cpp b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.cpp new file mode 100644 index 00000000..851c81be --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h new file mode 100644 index 00000000..9ca9171f --- /dev/null +++ b/Samples/IntroGraphics/DirectXTKSimpleSampleUWP12/pch.h @@ -0,0 +1,83 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#include +#include +#include +#include + +#include "d3dx12.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "Audio.h" +#include "CommonStates.h" +#include "DirectXHelpers.h" +#include "DDSTextureLoader.h" +#include "DescriptorHeap.h" +#include "Effects.h" +#include "GamePad.h" +#include "GeometricPrimitive.h" +#include "GraphicsMemory.h" +#include "Keyboard.h" +#include "Model.h" +#include "Mouse.h" +#include "PrimitiveBatch.h" +#include "ResourceUploadBatch.h" +#include "RenderTargetState.h" +#include "SimpleMath.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" +#include "VertexTypes.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj index 06f61076..6b4d7e4a 100644 --- a/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj +++ b/Samples/IntroGraphics/SimpleBezierUWP/SimpleBezier.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierDS.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierDS.hlsl new file mode 100644 index 00000000..c6507784 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierDS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracEven.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracEven.hlsl new file mode 100644 index 00000000..7964c584 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracEven.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"fractional_even\\"" for fractional even partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracOdd.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracOdd.hlsl new file mode 100644 index 00000000..acc5de8d --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_fracOdd.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"fractional_odd\\"" for fractional odd partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_int.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_int.hlsl new file mode 100644 index 00000000..db418915 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierHS_int.hlsl @@ -0,0 +1,3 @@ +// Compiled with /D "BEZIER_HS_PARTITION=\\"integer\\"" for integer partitioning. + +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierPS.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierPS.hlsl new file mode 100644 index 00000000..c6507784 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierVS.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierVS.hlsl new file mode 100644 index 00000000..c6507784 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/BezierVS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/Logo.png b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7e704a106b99487be0f1eded426e6c5a2c65a9 GIT binary patch literal 39826 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 YA}aUbQ|(Go1_lNOPgg&ebxsLQ0HMvfUjP6A literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SimpleBezier.hlsli b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SimpleBezier.hlsli new file mode 100644 index 00000000..98752539 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SimpleBezier.hlsli @@ -0,0 +1,229 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.hlsli +// +// Shader demonstrating DirectX tessellation of a bezier surface +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +// The input patch size. In this sample, it is 16 control points. +// This value should match the call to IASetPrimitiveTopology() +#define INPUT_PATCH_SIZE 16 + +// The output patch size. In this sample, it is also 16 control points. +#define OUTPUT_PATCH_SIZE 16 + +//-------------------------------------------------------------------------------------- +// Constant Buffers +//-------------------------------------------------------------------------------------- +cbuffer cbPerFrame : register(b0) +{ + row_major matrix g_mViewProjection; + float3 g_cameraWorldPos; + float g_tessellationFactor; +}; + +//-------------------------------------------------------------------------------------- +// Vertex shader section +//-------------------------------------------------------------------------------------- +struct VS_CONTROL_POINT_INPUT +{ + float3 pos : POSITION; +}; + +struct VS_CONTROL_POINT_OUTPUT +{ + float3 pos : POSITION; +}; + +//-------------------------------------------------------------------------------------- +// This simple vertex shader passes the control points straight through to the +// hull shader. In a more complex scene, you might transform the control points +// or perform skinning at this step. +// +// The input to the vertex shader comes from the vertex buffer. +// +// The output from the vertex shader will go into the hull shader. +//-------------------------------------------------------------------------------------- +VS_CONTROL_POINT_OUTPUT BezierVS(VS_CONTROL_POINT_INPUT Input) +{ + VS_CONTROL_POINT_OUTPUT output; + + output.pos = Input.pos; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Constant data function for the BezierHS. This is executed once per patch. +//-------------------------------------------------------------------------------------- +struct HS_CONSTANT_DATA_OUTPUT +{ + float Edges[4] : SV_TessFactor; + float Inside[2] : SV_InsideTessFactor; +}; + +struct HS_OUTPUT +{ + float3 pos : BEZIERPOS; +}; + +//-------------------------------------------------------------------------------------- +// This constant hull shader is executed once per patch. For the simple Mobius strip +// model, it will be executed 4 times. In this sample, we set the tessellation factor +// via SV_TessFactor and SV_InsideTessFactor for each patch. In a more complex scene, +// you might calculate a variable tessellation factor based on the camera's distance. +//-------------------------------------------------------------------------------------- +HS_CONSTANT_DATA_OUTPUT BezierConstantHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > ip, + uint PatchID : SV_PrimitiveID) +{ + HS_CONSTANT_DATA_OUTPUT output; + + float TessAmount = g_tessellationFactor; + + output.Edges[0] = output.Edges[1] = output.Edges[2] = output.Edges[3] = TessAmount; + output.Inside[0] = output.Inside[1] = TessAmount; + + return output; +} + +//-------------------------------------------------------------------------------------- +// BezierHS +// The hull shader is called once per output control point, which is specified with +// outputcontrolpoints. For this sample, we take the control points from the vertex +// shader and pass them directly off to the domain shader. In a more complex scene, +// you might perform a basis conversion from the input control points into a Bezier +// patch, such as the SubD11 SimpleBezier. +// +// The input to the hull shader comes from the vertex shader. +// +// The output from the hull shader will go to the domain shader. +// The tessellation factor, topology, and partition mode will go to the fixed function +// tessellator stage to calculate the UVW barycentric coordinates and domain points. +//-------------------------------------------------------------------------------------- +[domain("quad")] +[partitioning(BEZIER_HS_PARTITION)] +[outputtopology("triangle_cw")] +[outputcontrolpoints(OUTPUT_PATCH_SIZE)] +[patchconstantfunc("BezierConstantHS")] +HS_OUTPUT BezierHS(InputPatch< VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE > p, + uint i : SV_OutputControlPointID, + uint PatchID : SV_PrimitiveID) +{ + HS_OUTPUT output; + output.pos = p[i].pos; + return output; +} + +//-------------------------------------------------------------------------------------- +// Bezier evaluation domain shader section +//-------------------------------------------------------------------------------------- +struct DS_OUTPUT +{ + float4 pos : SV_POSITION; + float3 worldPos : WORLDPOS; + float3 normal : NORMAL; +}; + +//-------------------------------------------------------------------------------------- +float4 BernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(invT * invT * invT, + 3.0f * t * invT * invT, + 3.0f * t * t * invT, + t * t * t); +} + +//-------------------------------------------------------------------------------------- +float4 dBernsteinBasis(float t) +{ + float invT = 1.0f - t; + + return float4(-3 * invT * invT, + 3 * invT * invT - 6 * t * invT, + 6 * t * invT - 3 * t * t, + 3 * t * t); +} + +//-------------------------------------------------------------------------------------- +float3 EvaluateBezier(const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch, + float4 BasisU, + float4 BasisV) +{ + float3 value = float3(0, 0, 0); + value = BasisV.x * (BezPatch[0].pos * BasisU.x + BezPatch[1].pos * BasisU.y + BezPatch[2].pos * BasisU.z + BezPatch[3].pos * BasisU.w); + value += BasisV.y * (BezPatch[4].pos * BasisU.x + BezPatch[5].pos * BasisU.y + BezPatch[6].pos * BasisU.z + BezPatch[7].pos * BasisU.w); + value += BasisV.z * (BezPatch[8].pos * BasisU.x + BezPatch[9].pos * BasisU.y + BezPatch[10].pos * BasisU.z + BezPatch[11].pos * BasisU.w); + value += BasisV.w * (BezPatch[12].pos * BasisU.x + BezPatch[13].pos * BasisU.y + BezPatch[14].pos * BasisU.z + BezPatch[15].pos * BasisU.w); + + return value; +} + + +//-------------------------------------------------------------------------------------- +// The domain shader is run once per vertex and calculates the final vertex's position +// and attributes. It receives the UVW from the fixed function tessellator and the +// control point outputs from the hull shader. Since we are using the DirectX 11 +// Tessellation pipeline, it is the domain shader's responsibility to calculate the +// final SV_POSITION for each vertex. In this sample, we evaluate the vertex's +// position using a Bernstein polynomial and the normal is calculated as the cross +// product of the U and V derivatives. +// +// The input SV_DomainLocation to the domain shader comes from fixed function +// tessellator. And the OutputPatch comes from the hull shader. From these, you +// must calculate the final vertex position, color, texcoords, and other attributes. +// +// The output from the domain shader will be a vertex that will go to the video card's +// rasterization pipeline and get drawn to the screen. +//-------------------------------------------------------------------------------------- +[domain("quad")] +DS_OUTPUT BezierDS(HS_CONSTANT_DATA_OUTPUT input, + float2 UV : SV_DomainLocation, + const OutputPatch< HS_OUTPUT, OUTPUT_PATCH_SIZE > BezPatch) +{ + float4 BasisU = BernsteinBasis(UV.x); + float4 BasisV = BernsteinBasis(UV.y); + float4 dBasisU = dBernsteinBasis(UV.x); + float4 dBasisV = dBernsteinBasis(UV.y); + + float3 worldPos = EvaluateBezier(BezPatch, BasisU, BasisV); + float3 tangent = EvaluateBezier(BezPatch, dBasisU, BasisV); + float3 biTangent = EvaluateBezier(BezPatch, BasisU, dBasisV); + float3 normal = normalize(cross(tangent, biTangent)); + + DS_OUTPUT output; + output.pos = mul(float4(worldPos, 1), g_mViewProjection); + output.worldPos = worldPos; + output.normal = normal; + + return output; +} + +//-------------------------------------------------------------------------------------- +// Smooth shading pixel shader section +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// The pixel shader works the same as it would in a normal graphics pipeline. +// In this sample, it performs very simple N dot L lighting. +//-------------------------------------------------------------------------------------- +float4 BezierPS(DS_OUTPUT Input) : SV_TARGET +{ + float3 N = normalize(Input.normal); + float3 L = normalize(Input.worldPos - g_cameraWorldPos); + return abs(dot(N, L)) * float4(1, 0, 0, 1); +} + +//-------------------------------------------------------------------------------------- +// Solid color shading pixel shader (used for wireframe overlay) +//-------------------------------------------------------------------------------------- +float4 SolidColorPS(DS_OUTPUT Input) : SV_TARGET +{ + // Return a dark green color + return float4(0, 0.25, 0, 1); +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SmallLogo.png b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b09d91991638282fc2426bbfd4a517733ff15a GIT binary patch literal 23704 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 QcF+-zp00i_>zopr0N0Pd_W%F@ literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SolidColorPS.hlsl b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SolidColorPS.hlsl new file mode 100644 index 00000000..c6507784 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SolidColorPS.hlsl @@ -0,0 +1 @@ +#include "SimpleBezier.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SplashScreen.png b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c352b156fd090a57aec7da81b3b19a3fb5888b43 GIT binary patch literal 26474 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 omdKI;Vst01?W$S^xk5 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/StoreLogo.png b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..315472e10b9d380e509b2f041ea9ace5f994f5d2 GIT binary patch literal 24268 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Assets/WideLogo.png b/Samples/IntroGraphics/SimpleBezierUWP12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c70f68e2c59214e0ff54844ccd8ae5e955826e10 GIT binary patch literal 46540 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp new file mode 100644 index 00000000..a7415aba --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.cpp @@ -0,0 +1,658 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_d3dMinFeatureLevel(minFeatureLevel), + m_window(0), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), + m_rotation(DXGI_MODE_ROTATION_IDENTITY), + m_outputSize{0, 0, 1, 1}, + m_orientationTransform3D(ScreenRotation::Rotation0), + m_deviceNotify(nullptr) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } + + if (minFeatureLevel < D3D_FEATURE_LEVEL_11_0) + { + throw std::out_of_range("minFeatureLevel too low"); + } +} + +// Destructor for DeviceResources. +DX::DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ +#if defined(_DEBUG) + // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + { + ComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) + { + debugController->EnableDebugLayer(); + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } + + ComPtr dxgiInfoQueue; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) + { + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); + } + } +#endif + + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); + + ComPtr adapter; + GetAdapter(adapter.GetAddressOf()); + + // Create the DX12 API device object. + DX::ThrowIfFailed(D3D12CreateDevice( + adapter.Get(), + m_d3dMinFeatureLevel, + IID_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + +#ifndef NDEBUG + // Configure debug device (if active). + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D12_MESSAGE_ID hide[] = + { + D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, + D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + }; + D3D12_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + // Determine maximum supported feature level for this device + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + }; + + D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = + { + _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + }; + + HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); + if (SUCCEEDED(hr)) + { + m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel; + } + else + { + m_d3dFeatureLevel = m_d3dMinFeatureLevel; + } + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + DX::ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // Create a swap chain for the window. + ComPtr swapChain; + DX::ThrowIfFailed(m_dxgiFactory->CreateSwapChainForCoreWindow( + m_commandQueue.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&m_swapChain)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size. +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc.left == m_outputSize.left + && newRc.top == m_outputSize.top + && newRc.right == m_outputSize.right + && newRc.bottom == m_outputSize.bottom + && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_commandAllocators[n].Reset(); + m_renderTargets[n].Reset(); + } + + m_depthStencil.Reset(); + m_commandQueue.Reset(); + m_commandList.Reset(); + m_fence.Reset(); + m_rtvDescriptorHeap.Reset(); + m_dsvDescriptorHeap.Reset(); + m_swapChain.Reset(); + m_d3dDevice.Reset(); + m_dxgiFactory.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Prepare the command list and render target for rendering. +void DX::DeviceResources::Prepare() +{ + // Reset command list and allocator. + DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + + // Send the command list off to the GPU for processing. + DX::ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present(1, 0); + + // If the device was reset we must completely reinitialize the renderer. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + + MoveToNextFrame(); + } +} + +// Wait for pending GPU work to complete. +void DX::DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DX::DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + +// This method acquires the first available hardware adapter that supports Direct3D 12. +// If no such adapter can be found, try WARP. Otherwise throw an exception. +void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + DX::ThrowIfFailed(adapter->GetDesc1(&desc)); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), m_d3dMinFeatureLevel, _uuidof(ID3D12Device), nullptr))) + { +#ifdef _DEBUG + wchar_t buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + break; + } + } + +#if !defined(NDEBUG) + if (!adapter) + { + // Try WARP12 instead + if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) + { + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + } + + OutputDebugStringA("Direct3D Adapter - WARP12\n"); + } +#endif + + if (!adapter) + { + throw std::exception("No Direct3D 12 device found"); + } + + *ppAdapter = adapter.Detach(); +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h new file mode 100644 index 00000000..086d0cec --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/DeviceResources.h @@ -0,0 +1,117 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Prepare(); + void Present(); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + void GetAdapter(IDXGIAdapter1** ppAdapter); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_dxgiFactory; + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + DXGI_MODE_ROTATION m_rotation; + RECT m_outputSize; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp new file mode 100644 index 00000000..45d8f8a1 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Main.cpp @@ -0,0 +1,357 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + HandleWindowSizeChanged(); + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + m_sample->OnActivated(); + else + m_sample->OnDeactivated(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + +private: + bool m_exit; + bool m_visible; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Package.appxmanifest b/Samples/IntroGraphics/SimpleBezierUWP12/Package.appxmanifest new file mode 100644 index 00000000..a8a5fdf8 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + SimpleBezier + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx b/Samples/IntroGraphics/SimpleBezierUWP12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..6e1133489783ba56f95ce99442947350e19bc9be GIT binary patch literal 78231 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 z%0D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 a^&{qK0=!w-Knf%nBp5&mI8Gb15Ci~L%4N0y literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp new file mode 100644 index 00000000..ab195aad --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.cpp @@ -0,0 +1,548 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleBezier.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +#pragma region Globals +// Global variables +namespace +{ + // Min and max divisions of the patch per side for the slider control. + const float c_minDivs = 4; + const float c_maxDivs = 16; + // Startup subdivisions per side. + const float c_defaultSubdivs = 8.0f; + // Camera's rotation angle per step. + const float c_rotationAnglePerStep = XM_2PI / 360.0f; + + // Initial camera setup + const XMVECTORF32 c_cameraEye = { 0.0f, 0.45f, 2.7f, 0.0f }; + const XMVECTORF32 c_cameraAt = { 0.0f, 0.0f, 0.0f, 0.0f }; + const XMVECTORF32 c_cameraUp = { 0.0f, 1.0f, 0.0f, 0.0f }; + + // Draw the mesh with shaded triangles at start. + const bool c_defaultWireframeRendering = false; + + // Simple Bezier patch for a Mobius strip. + // 4 patches with 16 control points each. + const XMFLOAT3 c_mobiusStrip[64] = { + { 1.0f, -0.5f, 0.0f }, + { 1.0f, -0.5f, 0.5f }, + { 0.5f, -0.3536f, 1.354f }, + { 0.0f, -0.3536f, 1.354f }, + { 1.0f, -0.1667f, 0.0f }, + { 1.0f, -0.1667f, 0.5f }, + { 0.5f, -0.1179f, 1.118f }, + { 0.0f, -0.1179f, 1.118f }, + { 1.0f, 0.1667f, 0.0f }, + { 1.0f, 0.1667f, 0.5f }, + { 0.5f, 0.1179f, 0.8821f }, + { 0.0f, 0.1179f, 0.8821f }, + { 1.0f, 0.5f, 0.0f }, + { 1.0f, 0.5f, 0.5f }, + { 0.5f, 0.3536f, 0.6464f }, + { 0.0f, 0.3536f, 0.6464f }, + { 0.0f, -0.3536f, 1.354f }, + { -0.5f, -0.3536f, 1.354f }, + { -1.5f, 0.0f, 0.5f }, + { -1.5f, 0.0f, 0.0f }, + { 0.0f, -0.1179f, 1.118f }, + { -0.5f, -0.1179f, 1.118f }, + { -1.167f, 0.0f, 0.5f }, + { -1.167f, 0.0f, 0.0f }, + { 0.0f, 0.1179f, 0.8821f }, + { -0.5f, 0.1179f, 0.8821f }, + { -0.8333f, 0.0f, 0.5f }, + { -0.8333f, 0.0f, 0.0f }, + { 0.0f, 0.3536f, 0.6464f }, + { -0.5f, 0.3536f, 0.6464f }, + { -0.5f, 0.0f, 0.5f }, + { -0.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, 0.0f }, + { -1.5f, 0.0f, -0.5f }, + { -0.5f, 0.3536f, -1.354f }, + { 0.0f, 0.3536f, -1.354f }, + { -1.167f, 0.0f, 0.0f }, + { -1.167f, 0.0f, -0.5f }, + { -0.5f, 0.1179f, -1.118f }, + { 0.0f, 0.1179f, -1.118f }, + { -0.8333f, 0.0f, 0.0f }, + { -0.8333f, 0.0f, -0.5f }, + { -0.5f, -0.1179f, -0.8821f }, + { 0.0f, -0.1179f, -0.8821f }, + { -0.5f, 0.0f, 0.0f }, + { -0.5f, 0.0f, -0.5f }, + { -0.5f, -0.3536f, -0.6464f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.0f, 0.3536f, -1.354f }, + { 0.5f, 0.3536f, -1.354f }, + { 1.0f, 0.5f, -0.5f }, + { 1.0f, 0.5f, 0.0f }, + { 0.0f, 0.1179f, -1.118f }, + { 0.5f, 0.1179f, -1.118f }, + { 1.0f, 0.1667f, -0.5f }, + { 1.0f, 0.1667f, 0.0f }, + { 0.0f, -0.1179f, -0.8821f }, + { 0.5f, -0.1179f, -0.8821f }, + { 1.0f, -0.1667f, -0.5f }, + { 1.0f, -0.1667f, 0.0f }, + { 0.0f, -0.3536f, -0.6464f }, + { 0.5f, -0.3536f, -0.6464f }, + { 1.0f, -0.5f, -0.5f }, + { 1.0f, -0.5f, 0.0f }, + }; + + inline size_t AlignSize(size_t size, size_t alignment) + { + return (size + alignment - 1) & ~(alignment - 1); + } +} +#pragma endregion + +Sample::Sample() + : m_subdivs(c_defaultSubdivs) + , m_drawWires(c_defaultWireframeRendering) + , m_partitionMode(PartitionMode::PartitionInteger) + , m_mappedConstantData(nullptr) +{ + // Use gamma-correct rendering. + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + m_deviceResources->RegisterDeviceNotify(this); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (m_keyboardButtons.IsKeyPressed(Keyboard::Escape) || pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + if (m_keyboardButtons.IsKeyPressed(Keyboard::W) || m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + m_drawWires = !m_drawWires; + } + else if (m_keyboardButtons.IsKeyPressed(Keyboard::D1) || m_keyboardButtons.IsKeyPressed(Keyboard::NumPad1) || + m_gamePadButtons.x == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionInteger; + } + else if (m_keyboardButtons.IsKeyPressed(Keyboard::D2) || m_keyboardButtons.IsKeyPressed(Keyboard::NumPad2) || + m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionFractionalEven; + } + else if (m_keyboardButtons.IsKeyPressed(Keyboard::D3) || m_keyboardButtons.IsKeyPressed(Keyboard::NumPad3) || + m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + m_partitionMode = PartitionMode::PartitionFractionalOdd; + } + + if (kb.Down || pad.IsLeftTriggerPressed()) + { + m_subdivs = std::max(m_subdivs - 0.1f, c_minDivs); + } + + if (kb.Up || pad.IsRightTriggerPressed()) + { + m_subdivs = std::min(m_subdivs + 0.1f, c_maxDivs); + } + + float rotationAxisY = 0.0f; + + if (pad.thumbSticks.leftX != 0.0f) + { + rotationAxisY = -pad.thumbSticks.leftX * c_rotationAnglePerStep; + } + else if (kb.Left) + { + rotationAxisY = c_rotationAnglePerStep; + } + else if (kb.Right) + { + rotationAxisY = -c_rotationAnglePerStep; + } + + if (rotationAxisY != 0.0f) + { + XMVECTOR eye = XMLoadFloat3(&m_cameraEye); + eye = XMVector3Transform(eye, XMMatrixRotationY(rotationAxisY)); + XMMATRIX view = XMMatrixLookAtLH(eye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, eye); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + //Set appropriate pipeline state. + commandList->SetPipelineState(m_PSOs[m_drawWires ? 1 : 0][(int)m_partitionMode].Get()); + + // Set root signature and descriptor heaps. + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap() }; + commandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Calculate world-view-projection matrix. + XMMATRIX view = XMLoadFloat4x4(&m_viewMatrix); + XMMATRIX projection = XMLoadFloat4x4(&m_projectionMatrix); + XMMATRIX viewProjectionMatrix = XMMatrixMultiply(view, projection); + + // Update per-frame variables. + if (m_mappedConstantData != nullptr) + { + XMStoreFloat4x4(&m_mappedConstantData->viewProjectionMatrix, viewProjectionMatrix); + m_mappedConstantData->cameraWorldPos = m_cameraEye; + m_mappedConstantData->tessellationFactor = (float)m_subdivs; + } + + // Finalize dynamic constant buffer into descriptor heap. + commandList->SetGraphicsRootDescriptorTable(c_rootParameterCB, m_resourceDescriptors->GetGpuHandle(c_rootParameterCB)); + + commandList->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST); + commandList->IASetVertexBuffers(0, 1, &m_controlPointVBView); + + // Draw the mesh + commandList->DrawInstanced(_countof(c_mobiusStrip), 1, 0, 0); + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); + PIXEndEvent(m_deviceResources->GetCommandQueue()); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + // Use linear clear color for gamma-correct rendering. + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + m_graphicsMemory = std::make_unique(device); + + CreateShaders(); + + // Initialize the world and view matrices. + XMMATRIX world = XMMatrixIdentity(); + XMMATRIX view = XMMatrixLookAtLH(c_cameraEye, c_cameraAt, c_cameraUp); + XMStoreFloat4x4(&m_worldMatrix, world); + XMStoreFloat4x4(&m_viewMatrix, view); + XMStoreFloat3(&m_cameraEye, c_cameraEye); +} + +// Creates and initializes shaders and their data. +void Sample::CreateShaders() +{ + auto device = m_deviceResources->GetD3DDevice(); + + { + // Define root table layout. + CD3DX12_DESCRIPTOR_RANGE descRange[1]; + descRange[c_rootParameterCB].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); + CD3DX12_ROOT_PARAMETER rootParameters[1]; + rootParameters[c_rootParameterCB].InitAsDescriptorTable( + 1, &descRange[c_rootParameterCB], D3D12_SHADER_VISIBILITY_ALL); // b0 + + // Create the root signature. + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc(_countof(rootParameters), rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); + + ComPtr signature; + ComPtr error; + DX::ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create our vertex input layout. + const D3D12_INPUT_ELEMENT_DESC c_inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // Load shaders. + auto vertexShaderBlob = DX::ReadData(L"BezierVS.cso"); + + std::vector hullShaderBlobs[c_numHullShaders]; + hullShaderBlobs[(int)PartitionMode::PartitionInteger] = DX::ReadData(L"BezierHS_int.cso"); + hullShaderBlobs[(int)PartitionMode::PartitionFractionalEven] = DX::ReadData(L"BezierHS_fracEven.cso"); + hullShaderBlobs[(int)PartitionMode::PartitionFractionalOdd] = DX::ReadData(L"BezierHS_fracOdd.cso"); + + auto domainShaderBlob = DX::ReadData(L"BezierDS.cso"); + + std::vector pixelShaderBlobs[c_numPixelShaders]; + pixelShaderBlobs[0] = DX::ReadData(L"BezierPS.cso"); + pixelShaderBlobs[1] = DX::ReadData(L"SolidColorPS.cso"); + + // Create solid and wireframe rasterizer state objects. + D3D12_RASTERIZER_DESC RasterDesc = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + RasterDesc.CullMode = D3D12_CULL_MODE_NONE; + RasterDesc.DepthClipEnable = TRUE; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout.pInputElementDescs = c_inputElementDesc; + psoDesc.InputLayout.NumElements = _countof(c_inputElementDesc); + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShaderBlob.data(), vertexShaderBlob.size()); + psoDesc.DS = CD3DX12_SHADER_BYTECODE(domainShaderBlob.data(), domainShaderBlob.size()); + psoDesc.RasterizerState = RasterDesc; + + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.DSVFormat = m_deviceResources->GetDepthBufferFormat(); + psoDesc.SampleDesc.Count = 1; + + // Enumerate PSOs. + D3D12_FILL_MODE fillModes[] = { D3D12_FILL_MODE_SOLID, D3D12_FILL_MODE_WIREFRAME }; + for (uint8_t i = 0; i < c_numPixelShaders; i++) + { + psoDesc.RasterizerState.FillMode = fillModes[i]; + psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShaderBlobs[i].data(), pixelShaderBlobs[i].size()); + + for (uint8_t j = 0; j < c_numHullShaders; j++) + { + psoDesc.HS = CD3DX12_SHADER_BYTECODE(hullShaderBlobs[j].data(), hullShaderBlobs[j].size()); + + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(m_PSOs[i][j].ReleaseAndGetAddressOf()))); + } + } + + { + // Create constant buffer. + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + + size_t cbSize = AlignSize(sizeof(ConstantBuffer), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); + + const D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(cbSize); + DX::ThrowIfFailed(device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, + &constantBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(m_cbPerFrame.GetAddressOf()))); + DX::ThrowIfFailed(m_cbPerFrame->SetName(L"Per Frame CB")); + + // Map it to a CPU variable. Leave the mapping active for per-frame updates. + DX::ThrowIfFailed(m_cbPerFrame->Map(0, nullptr, reinterpret_cast< void** >(&m_mappedConstantData))); + + // Create constant buffer view. + const uint32_t c_cbCount = 1; + m_resourceDescriptors = std::make_unique(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, c_cbCount); + + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = m_cbPerFrame->GetGPUVirtualAddress(); + cbvDesc.SizeInBytes = UINT(cbSize); + device->CreateConstantBufferView(&cbvDesc, m_resourceDescriptors->GetCpuHandle(c_rootParameterCB)); + + // Create vertex buffer containing a mesh's control points. + // Note: Using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are few verts to actually transfer. + const D3D12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(c_mobiusStrip)); + DX::ThrowIfFailed(device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, + &vertexBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(m_controlPointVB.GetAddressOf()))); + DX::ThrowIfFailed(m_controlPointVB->SetName(L"Control Point VB")); + + // Copy the MobiusStrip data to the vertex buffer. + uint8_t* dataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed(m_controlPointVB->Map( + 0, &readRange, reinterpret_cast(&dataBegin))); + memcpy(dataBegin, c_mobiusStrip, sizeof(c_mobiusStrip)); + m_controlPointVB->Unmap(0, nullptr); + + // Initialize vertex buffer view. + ZeroMemory(&m_controlPointVBView, sizeof(m_controlPointVBView)); + m_controlPointVBView.BufferLocation = m_controlPointVB->GetGPUVirtualAddress(); + m_controlPointVBView.StrideInBytes = sizeof(XMFLOAT3); + m_controlPointVBView.SizeInBytes = sizeof(c_mobiusStrip); + } + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + auto size = m_deviceResources->GetOutputSize(); + + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + + XMFLOAT4X4 orient = m_deviceResources->GetOrientationTransform3D(); + + XMStoreFloat4x4(&m_projectionMatrix, projection * XMLoadFloat4x4(&orient)); +} + +void Sample::OnDeviceLost() +{ + m_graphicsMemory.reset(); + m_rootSignature.Reset(); + m_resourceDescriptors.reset(); + + for (uint8_t i = 0; i < c_numPixelShaders; i++) + { + for (uint8_t j = 0; j < c_numHullShaders; j++) + { + m_PSOs[i][j].Reset(); + } + } + + m_controlPointVB.Reset(); + m_cbPerFrame.Reset(); + m_mappedConstantData = nullptr; +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.h b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.h new file mode 100644 index 00000000..f2b777aa --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------------------------- +// SimpleBezier.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateShaders(); + void CreateWindowSizeDependentResources(); + + // Device resources + std::unique_ptr m_deviceResources; + + // Rendering loop timer + DX::StepTimer m_timer; + + // Input devices + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + + // DirectXTK objects + std::unique_ptr m_graphicsMemory; + + // Sample objects + struct ConstantBuffer + { + DirectX::XMFLOAT4X4 viewProjectionMatrix; + DirectX::XMFLOAT3 cameraWorldPos; + float tessellationFactor; + }; + + enum class PartitionMode + { + PartitionInteger, + PartitionFractionalEven, + PartitionFractionalOdd + }; + + static const size_t c_numPixelShaders = 2; + static const size_t c_numHullShaders = 3; + + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_PSOs[c_numPixelShaders][c_numHullShaders]; + + std::unique_ptr m_resourceDescriptors; + + D3D12_VERTEX_BUFFER_VIEW m_controlPointVBView; + Microsoft::WRL::ComPtr m_controlPointVB; // Control points for mesh + Microsoft::WRL::ComPtr m_cbPerFrame; + ConstantBuffer* m_mappedConstantData; + + // Index in the root parameter table + static const UINT c_rootParameterCB = 0; + + // Control variables + float m_subdivs; + bool m_drawWires; + PartitionMode m_partitionMode; + + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT3 m_cameraEye; +}; \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.sln b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.sln new file mode 100644 index 00000000..7cc3512f --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleBezier", "SimpleBezier.vcxproj", "{9F4DCF08-85F6-4277-8434-109931C9138F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|ARM.ActiveCfg = Debug|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|ARM.Build.0 = Debug|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|ARM.Deploy.0 = Debug|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x64.ActiveCfg = Debug|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x64.Build.0 = Debug|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x64.Deploy.0 = Debug|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x86.ActiveCfg = Debug|Win32 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x86.Build.0 = Debug|Win32 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Debug|x86.Deploy.0 = Debug|Win32 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|ARM.ActiveCfg = Release|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|ARM.Build.0 = Release|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|ARM.Deploy.0 = Release|ARM + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x64.ActiveCfg = Release|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x64.Build.0 = Release|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x64.Deploy.0 = Release|x64 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x86.ActiveCfg = Release|Win32 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x86.Build.0 = Release|Win32 + {9F4DCF08-85F6-4277-8434-109931C9138F}.Release|x86.Deploy.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj new file mode 100644 index 00000000..a8276c4a --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj @@ -0,0 +1,403 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {9f4dcf08-85f6-4277-8434-109931c9138f} + DirectXApp + SimpleBezier + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + SimpleBezier_TemporaryKey.pfx + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + + + + + + + + + + + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierDS + Domain + BezierDS + Domain + BezierDS + Domain + BezierDS + Domain + BezierDS + Domain + BezierDS + Domain + + + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BEZIER_HS_PARTITION=\"fractional_even\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BEZIER_HS_PARTITION=\"fractional_odd\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + BezierHS + Hull + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + Pixel + Pixel + Pixel + Pixel + Pixel + Pixel + BezierPS + BezierPS + BezierPS + BezierPS + BezierPS + BezierPS + + + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BEZIER_HS_PARTITION=\"integer\" + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + BezierVS + Vertex + + + Pixel + Pixel + Pixel + Pixel + Pixel + Pixel + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + SolidColorPS + BEZIER_HS_PARTITION=\"integer\" + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj.filters b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj.filters new file mode 100644 index 00000000..b24b065e --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + cc2ce594-f595-4717-8112-5d71f86945fb + + + ff1dd3e1-56e0-410b-884d-e8f8e675ef92 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {b863b83a-8e80-46e1-896b-904035394bae} + + + {f2fed98e-04ee-4146-bb6c-332ced8ad09c} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + Shaders + + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier_TemporaryKey.pfx b/Samples/IntroGraphics/SimpleBezierUWP12/SimpleBezier_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..ef3e885480c63f08af47e10b331b1e9ecdcb2262 GIT binary patch literal 2456 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 XT;3NeFMaa%+)J6gTOF;Mr literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/StepTimer.h b/Samples/IntroGraphics/SimpleBezierUWP12/StepTimer.h new file mode 100644 index 00000000..e6f7acf5 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/d3dx12.h b/Samples/IntroGraphics/SimpleBezierUWP12/d3dx12.h new file mode 100644 index 00000000..351914d3 --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/d3dx12.h @@ -0,0 +1,1534 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#ifndef __D3DX12_H__ +#define __D3DX12_H__ + +#include "d3d12.h" + +#if defined( __cplusplus ) + +struct CD3DX12_DEFAULT {}; +extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT; + +//------------------------------------------------------------------------------------------------ +inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ + return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width && + l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth; +} + +//------------------------------------------------------------------------------------------------ +inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RECT : public D3D12_RECT +{ + CD3DX12_RECT() + {} + explicit CD3DX12_RECT( const D3D12_RECT& o ) : + D3D12_RECT( o ) + {} + explicit CD3DX12_RECT( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + right = Right; + bottom = Bottom; + } + ~CD3DX12_RECT() {} + operator const D3D12_RECT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BOX : public D3D12_BOX +{ + CD3DX12_BOX() + {} + explicit CD3DX12_BOX( const D3D12_BOX& o ) : + D3D12_BOX( o ) + {} + explicit CD3DX12_BOX( + LONG Left, + LONG Right ) + { + left = Left; + top = 0; + front = 0; + right = Right; + bottom = 1; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + front = 0; + right = Right; + bottom = Bottom; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Front, + LONG Right, + LONG Bottom, + LONG Back ) + { + left = Left; + top = Top; + front = Front; + right = Right; + bottom = Bottom; + back = Back; + } + ~CD3DX12_BOX() {} + operator const D3D12_BOX&() const { return *this; } +}; +inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r ) +{ + return l.left == r.left && l.top == r.top && l.front == r.front && + l.right == r.right && l.bottom == r.bottom && l.back == r.back; +} +inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC +{ + CD3DX12_DEPTH_STENCIL_DESC() + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) : + D3D12_DEPTH_STENCIL_DESC( o ) + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) + { + DepthEnable = TRUE; + DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + DepthFunc = D3D12_COMPARISON_FUNC_LESS; + StencilEnable = FALSE; + StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = + { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS }; + FrontFace = defaultStencilOp; + BackFace = defaultStencilOp; + } + explicit CD3DX12_DEPTH_STENCIL_DESC( + BOOL depthEnable, + D3D12_DEPTH_WRITE_MASK depthWriteMask, + D3D12_COMPARISON_FUNC depthFunc, + BOOL stencilEnable, + UINT8 stencilReadMask, + UINT8 stencilWriteMask, + D3D12_STENCIL_OP frontStencilFailOp, + D3D12_STENCIL_OP frontStencilDepthFailOp, + D3D12_STENCIL_OP frontStencilPassOp, + D3D12_COMPARISON_FUNC frontStencilFunc, + D3D12_STENCIL_OP backStencilFailOp, + D3D12_STENCIL_OP backStencilDepthFailOp, + D3D12_STENCIL_OP backStencilPassOp, + D3D12_COMPARISON_FUNC backStencilFunc ) + { + DepthEnable = depthEnable; + DepthWriteMask = depthWriteMask; + DepthFunc = depthFunc; + StencilEnable = stencilEnable; + StencilReadMask = stencilReadMask; + StencilWriteMask = stencilWriteMask; + FrontFace.StencilFailOp = frontStencilFailOp; + FrontFace.StencilDepthFailOp = frontStencilDepthFailOp; + FrontFace.StencilPassOp = frontStencilPassOp; + FrontFace.StencilFunc = frontStencilFunc; + BackFace.StencilFailOp = backStencilFailOp; + BackFace.StencilDepthFailOp = backStencilDepthFailOp; + BackFace.StencilPassOp = backStencilPassOp; + BackFace.StencilFunc = backStencilFunc; + } + ~CD3DX12_DEPTH_STENCIL_DESC() {} + operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC +{ + CD3DX12_BLEND_DESC() + {} + explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) : + D3D12_BLEND_DESC( o ) + {} + explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) + { + AlphaToCoverageEnable = FALSE; + IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + RenderTarget[ i ] = defaultRenderTargetBlendDesc; + } + ~CD3DX12_BLEND_DESC() {} + operator const D3D12_BLEND_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC +{ + CD3DX12_RASTERIZER_DESC() + {} + explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) : + D3D12_RASTERIZER_DESC( o ) + {} + explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + MultisampleEnable = FALSE; + AntialiasedLineEnable = FALSE; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + INT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + BOOL multisampleEnable, + BOOL antialiasedLineEnable, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + MultisampleEnable = multisampleEnable; + AntialiasedLineEnable = antialiasedLineEnable; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + ~CD3DX12_RASTERIZER_DESC() {} + operator const D3D12_RASTERIZER_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO +{ + CD3DX12_RESOURCE_ALLOCATION_INFO() + {} + explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) : + D3D12_RESOURCE_ALLOCATION_INFO( o ) + {} + CD3DX12_RESOURCE_ALLOCATION_INFO( + UINT64 size, + UINT64 alignment ) + { + SizeInBytes = size; + Alignment = alignment; + } + operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES +{ + CD3DX12_HEAP_PROPERTIES() + {} + explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) : + D3D12_HEAP_PROPERTIES(o) + {} + CD3DX12_HEAP_PROPERTIES( + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = D3D12_HEAP_TYPE_CUSTOM; + CPUPageProperty = cpuPageProperty; + MemoryPoolPreference = memoryPoolPreference; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + explicit CD3DX12_HEAP_PROPERTIES( + D3D12_HEAP_TYPE type, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = type; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + operator const D3D12_HEAP_PROPERTIES&() const { return *this; } + bool IsCPUAccessible() const + { + return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM && + (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); + } +}; +inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ + return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && + l.MemoryPoolPreference == r.MemoryPoolPreference && + l.CreationNodeMask == r.CreationNodeMask && + l.VisibleNodeMask == r.VisibleNodeMask; +} +inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC +{ + CD3DX12_HEAP_DESC() + {} + explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) : + D3D12_HEAP_DESC(o) + {} + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_PROPERTIES properties, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = properties; + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_TYPE type, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_PROPERTIES properties, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = properties; + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_TYPE type, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + operator const D3D12_HEAP_DESC&() const { return *this; } + bool IsCPUAccessible() const + { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); } +}; +inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ + return l.SizeInBytes == r.SizeInBytes && + l.Properties == r.Properties && + l.Alignment == r.Alignment && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE +{ + CD3DX12_CLEAR_VALUE() + {} + explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) : + D3D12_CLEAR_VALUE(o) + {} + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + const FLOAT color[4] ) + { + Format = format; + memcpy( Color, color, sizeof( Color ) ); + } + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + FLOAT depth, + UINT8 stencil ) + { + Format = format; + /* Use memcpy to preserve NAN values */ + memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) ); + DepthStencil.Stencil = stencil; + } + operator const D3D12_CLEAR_VALUE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RANGE : public D3D12_RANGE +{ + CD3DX12_RANGE() + {} + explicit CD3DX12_RANGE(const D3D12_RANGE &o) : + D3D12_RANGE(o) + {} + CD3DX12_RANGE( + SIZE_T begin, + SIZE_T end ) + { + Begin = begin; + End = end; + } + operator const D3D12_RANGE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE +{ + CD3DX12_SHADER_BYTECODE() + {} + explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) : + D3D12_SHADER_BYTECODE(o) + {} + CD3DX12_SHADER_BYTECODE( + ID3DBlob* pShaderBlob ) + { + pShaderBytecode = pShaderBlob->GetBufferPointer(); + BytecodeLength = pShaderBlob->GetBufferSize(); + } + CD3DX12_SHADER_BYTECODE( + void* _pShaderBytecode, + SIZE_T bytecodeLength ) + { + pShaderBytecode = _pShaderBytecode; + BytecodeLength = bytecodeLength; + } + operator const D3D12_SHADER_BYTECODE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE +{ + CD3DX12_TILED_RESOURCE_COORDINATE() + {} + explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) : + D3D12_TILED_RESOURCE_COORDINATE(o) + {} + CD3DX12_TILED_RESOURCE_COORDINATE( + UINT x, + UINT y, + UINT z, + UINT subresource ) + { + X = x; + Y = y; + Z = z; + Subresource = subresource; + } + operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE +{ + CD3DX12_TILE_REGION_SIZE() + {} + explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) : + D3D12_TILE_REGION_SIZE(o) + {} + CD3DX12_TILE_REGION_SIZE( + UINT numTiles, + BOOL useBox, + UINT width, + UINT16 height, + UINT16 depth ) + { + NumTiles = numTiles; + UseBox = useBox; + Width = width; + Height = height; + Depth = depth; + } + operator const D3D12_TILE_REGION_SIZE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING +{ + CD3DX12_SUBRESOURCE_TILING() + {} + explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) : + D3D12_SUBRESOURCE_TILING(o) + {} + CD3DX12_SUBRESOURCE_TILING( + UINT widthInTiles, + UINT16 heightInTiles, + UINT16 depthInTiles, + UINT startTileIndexInOverallResource ) + { + WidthInTiles = widthInTiles; + HeightInTiles = heightInTiles; + DepthInTiles = depthInTiles; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_SUBRESOURCE_TILING&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE +{ + CD3DX12_TILE_SHAPE() + {} + explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) : + D3D12_TILE_SHAPE(o) + {} + CD3DX12_TILE_SHAPE( + UINT widthInTexels, + UINT heightInTexels, + UINT depthInTexels ) + { + WidthInTexels = widthInTexels; + HeightInTexels = heightInTexels; + DepthInTexels = depthInTexels; + } + operator const D3D12_TILE_SHAPE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER +{ + CD3DX12_RESOURCE_BARRIER() + {} + explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) : + D3D12_RESOURCE_BARRIER(o) + {} + static inline CD3DX12_RESOURCE_BARRIER Transition( + _In_ ID3D12Resource* pResource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + result.Flags = flags; + barrier.Transition.pResource = pResource; + barrier.Transition.StateBefore = stateBefore; + barrier.Transition.StateAfter = stateAfter; + barrier.Transition.Subresource = subresource; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER Aliasing( + _In_ ID3D12Resource* pResourceBefore, + _In_ ID3D12Resource* pResourceAfter) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = pResourceBefore; + barrier.Aliasing.pResourceAfter = pResourceAfter; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER UAV( + _In_ ID3D12Resource* pResource) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = pResource; + return result; + } + operator const D3D12_RESOURCE_BARRIER&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO +{ + CD3DX12_PACKED_MIP_INFO() + {} + explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) : + D3D12_PACKED_MIP_INFO(o) + {} + CD3DX12_PACKED_MIP_INFO( + UINT8 numStandardMips, + UINT8 numPackedMips, + UINT numTilesForPackedMips, + UINT startTileIndexInOverallResource ) + { + NumStandardMips = numStandardMips; + NumPackedMips = numPackedMips; + NumTilesForPackedMips = numTilesForPackedMips; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_PACKED_MIP_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT +{ + CD3DX12_SUBRESOURCE_FOOTPRINT() + {} + explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) : + D3D12_SUBRESOURCE_FOOTPRINT(o) + {} + CD3DX12_SUBRESOURCE_FOOTPRINT( + DXGI_FORMAT format, + UINT width, + UINT height, + UINT depth, + UINT rowPitch ) + { + Format = format; + Width = width; + Height = height; + Depth = depth; + RowPitch = rowPitch; + } + explicit CD3DX12_SUBRESOURCE_FOOTPRINT( + const D3D12_RESOURCE_DESC& resDesc, + UINT rowPitch ) + { + Format = resDesc.Format; + Width = UINT( resDesc.Width ); + Height = resDesc.Height; + Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1); + RowPitch = rowPitch; + } + operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION +{ + CD3DX12_TEXTURE_COPY_LOCATION() + {} + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + SubresourceIndex = Sub; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE +{ + CD3DX12_DESCRIPTOR_RANGE() { } + explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) : + D3D12_DESCRIPTOR_RANGE(o) + {} + CD3DX12_DESCRIPTOR_RANGE( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) : + D3D12_ROOT_DESCRIPTOR_TABLE(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS +{ + CD3DX12_ROOT_CONSTANTS() {} + explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) : + D3D12_ROOT_CONSTANTS(o) + {} + CD3DX12_ROOT_CONSTANTS( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(num32BitValues, shaderRegister, registerSpace); + } + + inline void Init( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, num32BitValues, shaderRegister, registerSpace); + } + + static inline void Init( + _Out_ D3D12_ROOT_CONSTANTS &rootConstants, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + rootConstants.Num32BitValues = num32BitValues; + rootConstants.ShaderRegister = shaderRegister; + rootConstants.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR +{ + CD3DX12_ROOT_DESCRIPTOR() {} + explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) : + D3D12_ROOT_DESCRIPTOR(o) + {} + CD3DX12_ROOT_DESCRIPTOR( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(shaderRegister, registerSpace); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, shaderRegister, registerSpace); + } + + static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER +{ + CD3DX12_ROOT_PARAMETER() {} + explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) : + D3D12_ROOT_PARAMETER(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace); + } + + static inline void InitAsConstantBufferView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility); + } + + inline void InitAsConstants( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility); + } + + inline void InitAsConstantBufferView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC +{ + CD3DX12_STATIC_SAMPLER_DESC() {} + explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) : + D3D12_STATIC_SAMPLER_DESC(o) + {} + CD3DX12_STATIC_SAMPLER_DESC( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC +{ + CD3DX12_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) : + D3D12_ROOT_SIGNATURE_DESC(o) + {} + CD3DX12_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + desc.NumParameters = numParameters; + desc.pParameters = _pParameters; + desc.NumStaticSamplers = numStaticSamplers; + desc.pStaticSamplers = _pStaticSamplers; + desc.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) : + D3D12_CPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE +{ + CD3DX12_GPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) : + D3D12_GPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + + + diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/pch.cpp b/Samples/IntroGraphics/SimpleBezierUWP12/pch.cpp new file mode 100644 index 00000000..851c81be --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/IntroGraphics/SimpleBezierUWP12/pch.h b/Samples/IntroGraphics/SimpleBezierUWP12/pch.h new file mode 100644 index 00000000..8aceb3ee --- /dev/null +++ b/Samples/IntroGraphics/SimpleBezierUWP12/pch.h @@ -0,0 +1,70 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#include +#include +#include +#include + +#include "d3dx12.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Keyboard.h" +#include "Mouse.h" +#include "DirectXHelpers.h" +#include "DescriptorHeap.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj index 834be222..063bfab2 100644 --- a/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj +++ b/Samples/IntroGraphics/SimpleInstancingUWP/SimpleInstancing.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLighting.hlsli b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLighting.hlsli index 0f5a2630..4a34225c 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLighting.hlsli +++ b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLighting.hlsli @@ -11,7 +11,7 @@ //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- -cbuffer ConstantBuffer : register( b0 ) +cbuffer Constants : register( b0 ) { float4x4 mWorld; float4x4 mView; diff --git a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp index dccf7848..4b3a9e1c 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp +++ b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.cpp @@ -34,10 +34,11 @@ namespace static_assert((sizeof(ConstantBuffer) % 16) == 0, "Constant buffer must always be 16-byte aligned"); } + Sample::Sample() : m_curRotationAngleRad(0.0f) { - m_deviceResources = std::make_unique(); + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); m_deviceResources->RegisterDeviceNotify(this); } @@ -417,10 +418,10 @@ void Sample::CreateDeviceDependentResources() XMStoreFloat4x4(&m_worldMatrix, XMMatrixIdentity()); // Initialize the view matrix - static const XMVECTORF32 eye = { 0.0f, 4.0f, -10.0f, 0.0f }; - static const XMVECTORF32 at = { 0.0f, 1.0f, 0.0f, 0.0f }; - static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0 }; - XMStoreFloat4x4(&m_viewMatrix, XMMatrixLookAtLH(eye, at, up)); + static const XMVECTORF32 c_eye = { 0.0f, 4.0f, -10.0f, 0.0f }; + static const XMVECTORF32 c_at = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_up = { 0.0f, 1.0f, 0.0f, 0.0 }; + XMStoreFloat4x4(&m_viewMatrix, XMMatrixLookAtLH(c_eye, c_at, c_up)); // Initialize the lighting parameters m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); diff --git a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.sln b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.sln index 1a619240..aec6524b 100644 --- a/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.sln +++ b/Samples/IntroGraphics/SimpleLightingUWP/SimpleLightingUWP.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleLightingUWP", "SimpleLightingUWP.vcxproj", "{A66CACF8-EB0A-4D35-A39F-65CBB6C546B8}" EndProject diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Assets/Logo.png b/Samples/IntroGraphics/SimpleLightingUWP12/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7e704a106b99487be0f1eded426e6c5a2c65a9 GIT binary patch literal 39826 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 YA}aUbQ|(Go1_lNOPgg&ebxsLQ0HMvfUjP6A literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Assets/SmallLogo.png b/Samples/IntroGraphics/SimpleLightingUWP12/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b09d91991638282fc2426bbfd4a517733ff15a GIT binary patch literal 23704 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 QcF+-zp00i_>zopr0N0Pd_W%F@ literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Assets/SplashScreen.png b/Samples/IntroGraphics/SimpleLightingUWP12/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c352b156fd090a57aec7da81b3b19a3fb5888b43 GIT binary patch literal 26474 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 omdKI;Vst01?W$S^xk5 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Assets/StoreLogo.png b/Samples/IntroGraphics/SimpleLightingUWP12/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..315472e10b9d380e509b2f041ea9ace5f994f5d2 GIT binary patch literal 24268 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Assets/WideLogo.png b/Samples/IntroGraphics/SimpleLightingUWP12/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c70f68e2c59214e0ff54844ccd8ae5e955826e10 GIT binary patch literal 46540 zcmeAS@N?(olHy`uVBq!ia0y~yU^HW3V3@|i#K6FCd#mvh1_lPs0*}aI1_o|n5N2eU zHAjMhfy+13**PE}BfliSI3vG6!PD7Up`a)~Ei)&TfuZ8o+~D$v$=}87?tf3^4|BTl zVdM0iMg}G2H5?}dA{PlvVn}Qe5OO%$+QAhjA}Tn?BlJkqRW6UY9gh}h>_~U)>WJzN zjj?zqe`opD+N$?&-~PV-d(ZPZ&;OjOJkQ@CD5N&=*`h24%b->ps~htD{vJn8?rmTa z^?1OdAn@$;p>)=x3=AKbD=X?sHrW4RT%XUt#87ZmPethX!~e~@0@T786ecn}P!f91 z%{U>5;e=ku2@!@95)2!HH>YqhOkrTisjP8QVpzq?@aBuB9V^3)m6Pv?Gu&7tvyy|M zmyuznhPw)r!)}Iz(8eGgrUQo<7OZhl(qlQWjIUWWEsh<}Q{RWi-RBFoul#KVyw=b1sPDx={7AyVBy1 zgWSA@0Vix^Ww^Mx->N1p+-vZ-+wQ;d!~6%`b>IFt$o;!r^?{*qmcz`o2NpN~ElkWS zTNl*#{4|S`Vcz%W%KwhH*8lC(y!gmuV~mby*T;y?9RW(d$18URO>|K_IrWjy%X*`a z^3(ouPA=zVSkvZzz;7G-*3&r$>fSLjb@N4BDr0b{`>fj|#XXThAl<~M@;d{=3yGK&Q^b9aaWF8rENIl);KF9}~B}^-wvL?oQD1Xu|60z)! zariai_6Y@}u0LIS+zqERZVF_+!c^+8bA`NA*Rch~7fVd|V;iO|%DyPIMb5Ti+oI(c zyJ;Eo#d4=j5SN>j}9h?>*tz z)UZZj`o!%M_$T;J`hD{7lkFl_M>`(*a4u2_S~5k*%QV&gDa+FNMou#qtO`84a^4k= zRUKCIqdapLlm+Mqx33g7DV?QycD9)F=_R_0uU?pynV$JQL;q#TF3!8na<0=aOuv-< zg8k+5m(5?wd3f7+n~!@WX-H;ER!c6I*e@m|gcw{mlAf79gMUVTXoS`` zts2pZr-Y_jO%0n`H}(0dkkH~#`>U0!xIdgIWm236AlyjHauE1TbyKa}Be`R+$ z`E}(>&abDw^1Zx!(fw=gm&ISjU%kKf{-V6OfeDA%1j!sji{uYyCM3Veo{_oZ;)j-p zD+Etx?3#EaWAR1L#p*lM-nFMcHmwl1OIwpKleEUDd&JyJG1_rAy@k$%lf znqPzSZW+G$^M>oqtT$|LEx#pxQ~j3v?Y!(686nwg)+N?8MJ1(Y%5n8Vep-tD@y_43!nvv<$Fv-W20 zmAhwbkJhgK?W;Fi`ef{3+xL!NK75aORCwm`+~u>EANoAuxqe((Tx8tuy>kAW=cvuQ zW{`X0_L1lZdrwyK$LT^P!YZ6^JD(i6am2RsaWT{LoLR77M8#h<-AcY0pA zO{8h$gc^(18A8)H**|Soa0<|u@PE2I&sSFXQ_JjDf7gABdKU$5+`hxhX412{VN<_Z z+_kQC{*}?@?^b%unA1NlTZ_H~2p z8r%KTw6!PmKB;_`drEq8`>F3wlz$d~zAc*5>T_}NmY{V3d}2QOE3_-3C88^KcBJ;zg+S3`Q zH%%K(oOcqU?niBdxYx>pbuzD@= zsqt$H)~s0fV}sj{XOF`D;;+_xt<1f3>z>#4Q*U2;yk7D;Z_W3}{p-E`@44a_I)?i zZe81dx4il@U$d;J^}Y8~-t5_`T@jwW*R}R*-lca%%ICF!{dgVN<3ZBkx$iFrF?X2>x1yNdjha8_CRKLHhruuQf zi-qS7-#L8t{>=LAUpZcTRBB(c+F!axcX93l+l71Izvx*!S2j-8ec$%~b?*%yCzl>K z?GK-~V6KMk$DdD{CO=-DvV7iLKYQCNGw)P>_xUq3J2o(OZ@TmOdG_KZ?|in$e?R&8 z-t+$04|@u}D1A@5t-9TNt?fEn_qu|=4?WgL=f6(zQ0`mE9=13 z;_E-I>&4Em-24968|m$NYIkLJsP6juqwL#T@p7(rK6hfP`YYD|*>~&jEB0Ufuj;q_ z+n9PF_rZ^Z0}1C3NAkbt<7}VzZ_5A6?GG=xpK-sc?55n?KUZE}npbM?r<8M(A1>dt zT=@K{y0HJ1uZvedzyJ5qZ}0OFe{Ou>{@Hzg|GLVRpNrnFUb)`txbkuNJ?AQIKQ8;T z_T25-_dDM2x_^AH{7j8M4*vo^U;LGPeE9|c?{?2?{{7Ma-tzgk>ZSR{3=HmknIRD+ z5xzcF$@#f@i7EL>sd^Q;1q>iyV_#8_n4FzjqL7rDo|$K>^nUk#C56lsTcvPQUjyF) z=hTc$kE){7;3~h6MhJ1(0FtBTx$+|-gpg^Jvqyke^gTP3i$R(Zu%AYpwa z1+bEmY+EHqkcA2nz5xo(`9-M;rg~<&$p&WT3g(u2hNkA`CgwT{Mh1qa`Ub}O#s<1Z z##SZ`ikZW0LUI|vCDsl_(8-&gNlw`P`g3_WKa6qRd>!;?V=BDPA z6zd!68Db590$4`|t{o*1;L_kg#Ab0xW*UwF1j*pkmRgaCLmNm2q79s;AW>}tj$$kS zqRjNnyu=)r{Nz%QzdT*+Dsl_-QZiGl3{1=ojZBSAbq$k^(sYeYOcHf1k_=OHlTFN0 zQ%qAWjZDnVZ1iy&gGg0StB|aKCu8+{Dz z2seT9HAFfE5qsE!Hpwj6Aj!hSLf635G#MJSi783CDM^MV<`(AWCaGyDFuRZp!)8}L zr6~sDWGu!YY=cDwQgCA?U60J-lKi4dBneP}fC{$Y)IwBIm_$w{k+BAkJJ+%jtHfkb zk!e?)Se6P7BqT9}lOZ}l78RF(6kv()Gy{`F^VH;2-4x>#LtV3E6I0zpV*?9avt)BK zBa<|fMrxiNs1DIJFx53O4>2^eGBmd`HPkgQw=yt*83k5_+mPb? zw370~qEyH9)VvZqNTr1sjB$1bRZ=Dj8sV9FDf#8anlMvQwc$2CIU_MIJvGHnAEpr| zfUdy zax#+>L5V`YEH4FGH^R#?m`9P!prc`G(==nhg4U4uDKG+Z6}7J1Ka&I-40G%!l8X0?7eowGz$X*Lkn|V3nMc_NUz-@CDlYX$-p=% z*)-AEJk87ilJIbMo9wU~ZETrll4O~bsB2+tm`Yuvi5qKxdK?j&pn?oK;F*(&!_`TN zX2wRTDF(X6hGs@kSDU9<=%ywa7$h4S7^az-Ct(i|h$w0lAV)C12($r>yMac^Qu9i{ zy*@ib8+{Bhgij#qBR~T}Ii;XpqMf;sfq{X6z9EQ&YDJbt*BXgmE3!1YR)o&byv!0i zBdBd?!brM6gM*OF6I_s(oC@+9x)8eRfXs^2oCuf9+|<0{%=|n%V?zTQeXu5U8LT=Z z5jqV`QFJ27Ky^Z*4Qb#SoP!{uK`w4~TsHdP@pjPIJ6H;mifBke9Y#YN6ciLjEg>m< zM}uoLxJU{Ck`#}ouF>EkDFjGTJes;jgNvjPAW89P>KY9$l0twa#iOZfG`L6#0g@Dt zrmoT8A}It&QaqZvMuUr_5FknMXzCgbE|NlkB*mktYc#k>3IUQ7kEX8C;36pmNK!nS zx<-SGq!1uU@o4HA4K9*GfF#AEscSU2ND2Xx6pyB^(cmH}1V~amnz}}Vi=+@BN%3gv z8VxRzLVzU2qp52&xJU{Ck`#}ouF>EkDFjGTJes;jgNvjPAW1Ra)WwB3k04(LhALGChK6PahM)f#7#dzOFq9fFFuY1&V6d9Oz#yJKDgLM% z14HtCPZ!6Kid%d3M)v1KR>^L=ZmF(Rv@bX`yma!EU6C!BGxWt=INDNgvR!G@yuqe( zVggIh1jcf0M$vPae_b4KKgr8KDMoOo{%JtZ@O<*GyRi+8KmSwA~_=ENC^bDs`N zelve7Te#Y1sczZbYGdW|8@~VBmtXrjntT5T?)?+m^i_ENJMz@e*?*+|T>Yaj>NEB` zF$o_(&-~Q?^?5`2$iK&@Sj5cxV>9cu--+p_|F-`LSe0!cuU^;ptVmOT;^nO__Al$i zKR;e`NA~S~!~3RB?>fZ_IriLl{LOWxRkf%t_;LO2`|0&6E8|uEw>?xnJ^$GkVV%0u zKT0I(FMQFgbnUI@vupqO{?V843D;BY_Eo+9_0sT{8J~8e59f*fL3Y>vFhtfV$=o~p zCF_iN>1DUWUt}L!Ieg$+zMAFFvE+Y&NpZey&+|WdeKy?X_nHaU+kdpZ3Nt;Q`s+hYQpfyx=K`K^J9YUn zcO;km3amX8So`He_w(x}f7;}Jy-_%7X>(udxU0>-=4*rTKGWn zP|fW6XC6zn4=rR*TEFMVPKzJS0*v?Wh<%xF`2JItTiK8Ip9Qn8aUA(C@MD6GYR}}U z1$OIQe#=e#@-gn5?txpk`}-0FT^n7xTCOZ9|0E_Ex8%%$XYZA`Zid7)A1Halzww-# z^o%Li6*mHQH=R7vswgI;_Uq)89p$@|{!P8Svv-cfNmrZp)N?!SzWzV=-ypTlQeef0 zu9QQn-n#>id#OY(I&;wH`Ica>1?DCaEahtRLvI~Puegz%(O@(4nTU9C!DLODBA=-z z7f0}GPFxh{_37=(`8-a7E**nM%nHPunrNFFR-hZi&O0?oYJ}? z-i}-FdPw0X!M|Sf7y0i@^qcd1K7*Dd8{d)SztIBq_O%7u1vky%Y5dr()Wy6({os~a zF)Zbl3J>GI1_tgB*w)UnZi*T2OOvemJ|Rp=xsJxNf@c-Gp8ScnKEv(0PxR+b4K=4l z=UzYMUaoau!smZKd)n8^SsoRdDtG8v?4zSzDqb~0J~xH;2-p67vge7wv8-oBwl_~V zd$T?F(0ZiyOe)`QrN#es9~~B2Y*RR&_0{g#C$60}T$gjI=A`yzOI_t|T)Z=_W!Ib~ zk7@({Us_`Jigm&U#$)r;PA+a_yEy9+PxF~mVsl=tT)Ki|*|8uWffoMlnlA;i>Uo8p zZ-2?)e`1ZfPTptfQ|mVt9#606?eLnCSi9-Z<0Soa=bJelmohwAbYc3cqTYiI)<2(d zeKfZ-ZdAC``6T&9YQl_f4u70>{Ev@Wb&h+{EY~Y}4(k$MHtj#u=WuAb>6O=#pZ#Vh znw|R1ca2@4+-qr$O#{yn$&xRA-i0eTHZ0r|H}n0RtKP{1R~LBCe05e-p278@lzOPn z76u&+y?yJA=TEDa{`nzz#hVhhj$jE6<|`#a#WB%SR&H)|ch!w-68mKS{BpHcyaKcA z*?Y||1zt`yNO1Gr(8F+hvEWHT5b=DsgncO;^rTIY6wuob0vy{s?PI1pU?_qI) zU)W;J#0xK37M+av^4B>3&ClPZj@*HBE|qm((R&_o(_b`4AghF>mFuBNyV2*hhHEB1 zTP3XM`J zPVxl&Na5XYxKm84q|)i@m&nQqYYy`5+c6>CxZ=%kuJsJ6Hka&uL#{FKv7f0rzimc5 zLu+<;r*!vh6UXo)ypw#dyNJ7me_?1B(cWHsCcpRJlT*)nF3$8@aqoM_rk^igG;8tR zy%z2;y)AS3lBfht-w&IgZM+fpagQ!nwaBNGOULK^QC{rcBE-hhpKpAtkD;lou!jG$ z9IN1>Jgxnwwlm-5zrKC#wATEv#4fQFq2Y&(6#sgCE2!Rc#bL^WbsMH@9W=NWpx6@- zR==T7>o3!yDz6n+7Ia5@$km_CcXhPm%1lzSSju?eL$lKtS8nx;RSJEPNwXJ5t@GfS z*3o2rh-vq)fV)#KHSTRly>{TqdA7$3-aXwUv~F@!R>H)RQ%ib_>lu}HPJL^5_3!*y z&kw7g_|}_icvf~Q!=z5521EI!uYWr(s9)lqu*{kcJmt4zRFA#aIVjcSjMBolf!jb zqrs=+QVfS-j$+V_Zq?T`fb zeZGmECu8b%T{1e*e(19Of$&7_cbeA|?|hmOWEnO~HTd|1r|$yU@&wIfBtrud<2AE* z56w|$c8xa_$}r>cs1BpZv(0f#dWm}|1nyH?x~ z`&hzb*l;d@tKhJs*{3~6I^)?_>h7#~Wz>JSQtd=e$YVPhC58!?*)DxeWW9^TU*RN;DV7aY>jeKNDGL^!agn ze1<^>e{fgljt$p6%N-jy@0qm6bNHyvjqE?nrg2U{=9zHFe_0z2>xEG>tZd?PC+eM; zaclvD^sh&YY*xr?zEU=x->9)bI_<%qPm;&7{+D;m*Z325Em(V!{_=|0j@e2p{%&K~ z)?3Ws{Z_+2dV*N;q94m+ehIZMzIAMMC*R6&-iO&0EWbU)J_cqR>8uHvrEtr|(7wgv z;u66(iei7NRxOasQ#rJ?Dnvctc;Zy~BlB(cHU5|&6SU@G8n;R7odu2?Ra_@$NL4L( zHBT#LX-m?w4yHPRYiSb_QqFPy^$3HEy;^GnEN9=j_`u?fl3Q@d9gPn!9!5-F*V)ryEK$-F*l@tn-_12b zf0cG<%B)ATI)0^a2nyc_jndOn?3mqQxG+S+;%UD2L$A&^Hj5^FG;(8!I9%i)V7TmY z>mv6>9n2?;r_b1Vt<~wCOl29{)%`^i|NSa9dzoV*x1q&9rDh}J?GFy~>Vhw9)d_zx zC1#;b-)DXPaH}V7%G!dL5d$A`N+@KATq zcRAr_PdxlRmrOlqP`=lfZJOJ1;V*NxTP8jGHf3Jn(}!IpXTKv|tr=Da zg|!%p8BQ)avOaQ^jmDdWKCDbG-&>n@d7pe8xWY_*%gqAUK#O=yBayG0o;+C8&~jY% zLPuGZLE)mR%`N?}z1$9NFZ*jk;pLL&c)myKM7<19cqMdDu zIX`Efa@o+M_^faK&pH+3N$j(axw0&X5@*S?U+pW(B=5tSFzpU=fQ#zzmI_=lzt1K>Z zUOMl1e_v(Y(U{4TqB$$bEvveGVx7~0qs|@YxH)(WwY+TCCGmtT)6`=3C&r0rq@e7wuRcxjk|EP?d%^TmUAg0CqpW@ zuV^?42`(3Dbj*(D?dICU5?H|HwCMJWZ~j5d&h80k41IaTXQc96GU@*O&n2Q%L6kxD z>c?4evb7#ZzEpn|&VM83!TMl^=9Nu`KlM(E!5}{sBXM-o7bT*YLUcViGaH{$9?_wiQY;weW%=XveHAv zbmh&&`yL6hi;p<|V0OQ{%F$)zUYC~INfTE@R?c2g%G@pP7Ny1`wCknPtPQ!d7%v6X zsjxm_E{%%RSuAr$fiI3lc4DMLVqdn#yw~Ea<~l4)v>MY$?n$p0z&?WM@9NEI3G~#i6_MKncQ7~Cj@>hqS z6ED~1e^z|wDyJ5_h*;@(LR4{vCC68F4T}XIUpx5Taq=>{IU{{JhoQnQizzD@_pN4* z-+6Rq`MPZ->V1!Pq->hC*i={2t0sWX2@(FA30ZH~G+Rwl1)w|ufTooP7bW?ND>hv_KGp|U>S2~#%R7prz| zTe)z8lHsETk@Fr2rOuo?g>UkUw3`YdFV@axp6qgD>w-gv77OlP@vPjmx^2#G! zKMt`>DCJbNSuOCoVT)b&#Tje0rG9<>8UAF4(xEnm`*#Djn`(wusb3IU_jJ$sMOTYv zOjq(yT3L{NE6A;0^V!+W7e1K1m2vd+(Yr2kRxYb&+Zp%J#fOZ32X38s>E-f}6_>eF z@}78xc=bA6e)&!*@~2F6UMD+8>TQR@w+CN)Jq_d&d~$X|`3j@;%kL?C{LpaRUd2S^ z&x7p>GYoF+*}9XdF@hyry`#{#;Ce{%6^)GwTK|=r7VCOF<2}uPP1Qc)R^1K%V{>a% z)<6HwI9))uX>q>lKEW{KyBaALsp`Kz>sLgxeX*$6zh$Shp!|BDn8yZQ-BHUQ9+u1b z_&%_2y8FL%UF+(5SRQ%&S-A3l9Q#dw2Fs9;13e6zR3;?+j&Znp;=r+6RkG98u&meo z_BWtfL3qXVbM5;-{kpdHJm=5NN@Z>nq!KJ%@yvYH>g*sVQ|+SsJWQ?m%v90C(#w04 z=6sBbXclL2cx(7P?}V)jlCrb!zqaUEXB6Wri*OhVvOUuxxx%2|fyvz9ddWbrms zN?9G+AoOt41}34vrB6>Sil5v+r*EqwgBP<=^dy&)Ys@b=ec5wz(u)IYvR-F=ne$XL zVp6VyQ}8MGfURd93ToahNjfz1=#`f9X|i9M0@Rx(uYchna>qi+*Gp#paV6F%oZL4y zzbFm4^~mQ(!wnwa`mWDKG9D6wFJ5F%YCG=Jw8c3p`K14W_9crubd(Exy1I-$1qfui zbS+d~dB09V?{}5wwyG^h70zsYxhQ(ChNJh!B;7B9OCn#39XOt2`Rdxq8QVJRIxEgC z*_1HrLdLO}{WkrUfBUR5Y=0~&jh0}ljSzy_udE4pHhJ!lC*1zpok)$!V zq1NDIWn*uU&Y=m zdU7`Y3j*zmnF2QDpB0Rg-8=IIql+g8KVzbtmWDKUM`WC%XT@)iU<w|CN0%eXFd^xP`w!vn2W#2*S57*ZQ1n6EWgi|2Y=z&km8z=aA*_vQZMGK7pn6VGH>%7 zEIH3^s>;FbR(6Z6v|w|&(-d8oyM={+_~ z{mcgU6%X8a=5KmAa4WVOkG4F6{f@xn`??kN@Ni|m4VNtpDxEjI zFiM)HkTo^zK5sm_$B^*&wZcXm?57TwmFgS?U}>shI^#@(q1>bvaI&)Y-c_H zzuYRlQCOp^J*#c)!z)&Tn&BbmK7Tl%CALCCWIjiAy5`bXF{^Dm8U?l;G7LzOsMgvT zbnxV{^WPTCRY;4Tx2i?DtJm|_PR{4g0=DNgEx9b`&g;1Ff2i4K-QKWEtES6L+8i`t zd2Q^LNr@IS4mGyl58m)#_Y+3@EJlamO0L~tbF9xn;*5_Ob46(C-xv_9jx@ihkL?f)Y! zmf5rX+-zu_^pQ6?y!|a(WdDsT3-({M*l;%WphtCTO_ zIrltRn2Skr-{voS+WF0z6COA?9UI%|A(_gs#P+b(cB>C09{?Rd4__hP&0ISD2OJhT zo2~ksWA}7X`WErc54(gJ(+XDnd{DM&`>`HcfnL#%(5`QKE7sW7WCCxkjEA+z%GW8tJ~f z7qnUO`J^)zCG*VYrj;n)^;MK?O`86MIg)jgVb6<(d1scryt_THN%PYN%Rigv@9BAY zX{E@l^Q%o%_i(el5xn)~!ifyW-^r)MJ#(AxEe)9&)w*TVYMUzFCG2|(e_dZ>$ypFO z%_GCBc|FIK4Tsk$oso3={~ly5l;_d+4|>kI!{A6w@e5HRJ9L|TU8>kUoItY-Q0 zX0GX2+BbPmE!%QM*EuIP36)%7iVU1>V%K#}O>P$d=7m00aTAJ+_VeVPd~i0Z(Uf1l z+CAAkI%`AJ^`)D4PGpT2*wzx0@!`~=;)rEu#AZ)YkqrDCe=U9Qsleqg4htxVoNq1a zm~n90^O|!Wg)&}zI+qVN&aWvFE#WCy%`h=>qUGBJ)!NnfO4x66a$J``lXYBUiHw!? z&OLrxS{^CzJ$-Mo*ner0g4X6ll_zQuGoQAd_;XEybJ20fdZoR$`yziBnVPUM1RmZt zE9h+3mW4@yF~8Za&k0)9pW%~#by0WMi&HCKCe0K5#GSk{fOqSEfoq~w7Y*;%oe?VR ztKD^@ErUC>D<%G;!|E5){Qne%95H#n?ycm~IXf=x*nHUb!XziV`IC2vy1MlW?KF*P zIs7Y+b^Z~af-|2s%}|z=%zWp!E9Dexxyzo6BdL>oR~URT@K!2p;pr1xSLBYSEEHSrCpuH$)AP$~+OMSK-mjQ0Zt%AGO+~}C zPZJbBGdjASJ{)Dcgg?`uopl1oYP}9G8E0J{=h70F=M0bDEByLju-NpS(t^qbClVKT z@g~|?sB1OJpXE$aZ{mu&;-VJO$;c_9#{EogwykeK_Ci+{Ue+T?*EEc09=a&fF0=Tz zPuc=IwF3nWvxT^t{rwIzPg^I$&h;|Xllk)6FP*g)BqEtToq2v(uTh`EB01^nvtv9a zoIbrXDxMtE4pnXye{+TJ>Gn%c{2RAy;g2x7-7v#-My~1 zx8&c77as+gX7PaE&e2Fb?*D6OI{9<4mVr7GrzJJzi!mA%s~;DsXa+gBl$1@8pRLj=vQtH)I-Fh7XoiyPIu3r0E204b0v}k}nz+=xijzu} z#OAr=Fvdi_)|3BqZ=uGUBT1#FOqQMuD?F%T(hz>$yr@v8UrbryU)F?bw>PGDY`%4L zKfdW$wECR7f`D$A{L!pj0q2dAUwVB|-ejr9#NRyULe8V0wKIg=|DHZ}wnOZ8|Hh}% zEtv`58rip8-f?F3Gp>v|TD+6XpFHn!kP7{+e^#C0X?_apr8!$9mjt!VxO**f;a4Gh zg{ghcEy*t4O*0KRf{WWSr{*j5O}zU;*Xm7e*bTOc<`2Jg_C8kc(U6@vXOoX!_Z+nZ zKlTS#LlvqRcuI<%KImrEQLy}@#qXSdCV7*O;X;MDwNCz9cWAB?V_eqjbopu?pXZD2 zq=<7#UA&FUSY{m1df|9Q(qrB6*ORUY?G;M=tTju>aqGWH{Gy9uABn1LJy6o*$GY;_ z#m1=FicaeuJfD?xW4Fvk@8XFEgL$4GTikiSvzK$4%g)J7+cVCr;aczYB}!m>&zv8| zPQm5BxfjfoQu?j4pLudc^TLl?+%#$mr8SE#XsFImX}V}%5!jM-~c7BDiH_!|GY&*nStXXEEK*2(GSQf;+qyCm9X%gTB#bv4{J)6oCYoA1?| z{bZA z|Ni&i4^_YRJ^$17?0&!IqNHD0ZU5J2D%=-XB+hX7yvErL6PMLH&7OFAozP#E`hD(K zGX$-Kmv$D5Sj_WSEM*(4p*(F;cth9BJuPipE-A+DiGis5)M&eGk!*jp?o%dvq z=op$Sx`)}R$+i$<$ zKKm{4^M<=QCv7j7`A(iNYguN)vRrAO_Q^i48l6@*YYL@n3NruNcmI96a;p6uf!}`% zT2*$hi`LooH0h>pSogZ@-FX+c`QG-s&Cl6s`}=R*{rBaE_r59Hef(|N{>qAq8@c7S zH%%V@_VmrVVD?yZ^|t~w^(BW^&QkKNw3=3<7A*ZdO=iNBHJjPEY*+c2+!PEkRo$8( z{x9SNYp|kuxlF6juI`M-eV=ElZ0`q$#ao6o(@sCl+8U$l=jXqE9SG>1JFmY^@4Vl6 zJ-u`1&+AX?KAN=ig;@8x*pk@oFOG>C*w5Ja{`cPWTzkU1m?cKY) z+U@)H?%la_=gxf~Tvt<5b0^2_`|G!5*GtKR+o`=@W)?YDWm@8)gqpMCc3 z-M4Sw-u?Uc@7c3w@4kKed-m+tuU~(y+Iu_Cyubf@e}C%+^t@!xo=V$Tr^K7esJvlj9-QUmO|MoW7L#emR za&Ir2@~h5%seiJc$E`22maV5Q8ZF&&zyEd3k6pWW@2)HV`|R!Q*RRXh$M3EC{_XAW z+uyHWe}8{}{r>xTv$y#=G;fKTTN3L&ZEDE{Q1m`)OxgcDX=}y5H#aA%pPy$_`>D6z zzV6qTmz$rTpJ!89Ra&|=La*(?{cX9|OApVuG=ZzS{a)=Wo83x8)XZvdX;W zc1N(+JjUzg$A^i#Z*P1b{OIV@r^n_0U%7g9a=%^G$45uI)6dVhul)4n<>lq#&&6Y{ zpBRH25ZZf^Ni$zdb><7FeTy~Sn0#jo{r+3G|90;3=&Fi}9sBmxeSdd%clrB!d+I)a zx_Y|&{k^@_<$s@@eSN(B_Oi?iOP(g}j9Gik!DFRy`=(jzJ>p-^*`>8=fqTtGg9lGo z|4jY=VLgj;bktqjmL-lE%{os-gVnAmK6|ln*=d)e{qOgGU7P>+%lSW7)aTcHdZ|9& zruy5XN1q;@oUFe3Y1aMs-*?B_%WgURo&PJ-Pto)vse$VIXD!RTwJi76y4OKo-(UZp zeS7xq-Me4Eetms?+}`T%@6OIPUmw5!-^KnqlV!cF-wk7)Z{Pp-ZGPS7+4p}une1=( z6BO~`;o;M#PmjIMJA3*2-+$};gY<4XmoM?Y?{U8B&c;XgW+jT7ovjG|{{8*^{rh+B zto-}xtN*?~Cr|6||1;VC=j7@7@nzk9eUGzu#@N`|#l^+dJ>PtO-`AJR=hyvu=`LSe zQdwF0^~tM0f95>N+b*5A{QdVg!Z(X6ydVD$3Eq47>ZKZi-v5?&&K0b9yY2S(_xJfP zemy4r3dnM=QjNR zmjD0l|0nr>dKXGC8{D~AxBd0+eG%VfD`ljY-fuV*_4?1&*zGTNxn4K*-F^G*j9;^7 z-@gCn?EN3j^?%u)r$4VcmKt;a_3q!GK>z=u{)hYgx?h<|uf$^Sf4}{<%)^#TQF+`P|d zIiMk0ma^V>-&splPQM51Zm4{?boJ1ibq4cAS>sOFtx@YW>|4ag#Vl3xt$6<2`E&Q~ z-gnQ&&Z^P0a?RuWN1x4ESG523+w$GVkGs$8i3LTOwY{|thq&B?8Q*^Y{dx6jy8ZWJ zhIjIEmkvAYnmuCf?|pJs^x@lf?b(StR<>()X54;u^K-iW*I@g|MzCLdH%0`&wnY*zoz)@&wksSZ znSoa?m;G5Nl;3eRwX(Y0`iRdY!{+Y)dEZhi5Bn{>lD9qj{(8;Jb(8-y*Y2;c*m3{; z_g{VgnwtNG?^?O<`Ln{}`u%wqM3(%$XmTTO+v~5tn7g=@pLMMdIV^hXIRXlmBjcYU*+_t{)^e~-r3*tg5p>gOl)Ij!w#WU9<(J1Fy0 zJK|uVw~RZt(B&^@&i+4o#30Z{IPj(9ff@mRQf z-Rs}B?cdKIx$?a3@x^jeyJ^cbnB5xww%aKA?fR-LoaN+vB>dDT!(d&FeP>qBeD`8S zl^DbCy8GY5E*gJdus9;9CWc2SeEE%F&nj1U6$6oXIomfY9ewN`p>V_dQJ!KN`$?7W z&4nwc#knx5%rVNo`S}k-+l9=4my`v{drKd z@x?Aa;UlKWu`28@Knw;Frzd`u?fm)WVt~WE*-e+^ zjxN#45Ln?ScAM$7Bcl*sd0;Eg(mK5vJ?wnS7pFG0y%D>6^Je7jZ7SDafBpLP>)pF| ztM-Blb5Q;J_U^B`z5Al?+uP)r_d9!UzW-L`p0!Za>}8p^o)&G4(F;F4`Rd76U%q_# z^5)B*KY#u_s>ygdckaA-^TA-woG-Qe@4l6jmn+*XYjVCwE_~TJqfeg~@NIE0zLck$w%>kh|L6Vx zhv)zQIlumTwxouhzW)F7^*{CNe{ZjU{_}Hs_qynHeqpPxo_u-o=FOW=j~+ex^yy`F z|9N(mMO9^Gg@uK6g@u(xMky~3e|vBwfy-!aMp3KIuAB4b&6_u8&XOr|^77YTe|`J* z?cb`}zyJPz=sWi8bJgC;njQ5OH8mAC-hMA`&XIU5H#u{`>s?oiDmPh0&Yd%7&b&Eu z=kl+8zk2oR^z-xP%$qlFetb;KocNeHKG&}fr4wwmW-pVSvVBoE??fv$n+2y9DZEiB z5nh?A?P$Gpm%)FnHd%j#Yn#sKZIb(>8r-#IiK)CM$F*I?Ucsiyi#xlYe){|Swf&Fq z|F6#8-o8F=Z`Jp2Z_l1Rd-m%CGdOYX9YLZk&f`8Hd z(z`cr-u(F!)YSWV^k}!Z{yh8ok00Ij>z<|8J^S(|$Ns4NYjM_E6>g%(&yTjMV?W_I#?Ay0*X;v90_IY}oT@%^JCZY7I zZvXcSg_liUfBk!Uy8iFK`{bjfZG)5S3)p5(D5$C`Dl9B4EiJ7p{CLq_es9G;NL$Lj z`rn_QSzDuYc0Wzp8KE<4S){JmoU?*Ku0B_nP079e@1y+xkKgzI|9kuPZS(c_@7%k4 z@6Mk6dw1^Lz5DjNvcm^WdR_b83MWo)S=ns1@m-t!_uwLLqr&^&9g54!sz4SNmKGNN zdvo-2zum7FKR-YGZ)a_58?7U@`s%9O+l&`;qjt{AxN>;udzC3&$98PqvW4*=lW0R1 z+l!roU9N^j;%oLLws-xI?{koJDK|NBw0qxvjgD&yN+uGy@9O?NKYhCUeeL_||DWyu z9q&Gx6tS#3@1owVyo<5A;l<%n?7zhe{yjLfjm;-z|NZZv*4EEYPbawO?$TTO<@>*P z_y5km|M%V3uccNhj%?wodf}_DuaE!#q+363U(L_S`ul6XzPh?PTtENbeVe|6bC3h9pRTWiD+R}34kKpgW|9<`Y_4T#+?z_`ES061Z zExM#D79Jk1AGfFC-=CYG)6d)gdhytQ-_Mt2yK`qhb7q{o?)AHO@9JJ}uY1jI|Ks4I z*E535CmGznym_;+D?7iHvmf8OZ{oW@#>KtewtL@u_FK=3w(iK}4Q(wAhb@opSG4V%B{A|r*CphWH zEUd_09pLdXyG`=VllbS8Y-B!NX?vaR^rD|b*?GyrfXv(PzI<8o+KM&6{keBw>cnk( zz29~)n#5i%iQOKx)=leZUitPoejbQ_Ks@iPRm`;DN?LL~c`R1Qz`G1a8?XCOz z>+7#~e95{tV&UrQ>gnm}pWe)SCS!Dd_k}Q?M#+hb9hW3NZp(CE{zNhH#qYm=|2{7- zxBv5S{`cQ?`)_ZJEiWy-y6x@HpF6XDd#>e4JGa{=SlVRv@#AM7KL%x;mzurBld?P= zGAv$ZFE5`lDf8hE`|fRTZ+?%e!{86 zFO9P{-G008|KIoKzMEt8=G)cIdgQ5k#NZFRY4DaKa}<6>+vhJ}v`{(IePl{lGc)h+ zzmFd$U*5)Dz1gi^>4@gdZFeV}Ip4kD)->JdhnIMw7tY`*Jo8!FWbH1oFL&(k-2eZ8 z-TuYze}5h=%Do+N{vK!frwISalQx*2R+~2K(t}^S=So~Dn8N%lCFZak&(W@_0lK9n z3m5*sVVWyaef6aM9CP2`8F%F4I9hHyt?XCcs(mExAMudWY795 zU2a=)ZzTJF`xEk#EqWn~|KmyjB9soUnfcOqj^@ckPg#CVMbl0%gNv(w9NJnn=h%r&yk?ja(>I!)-cus5LL(0N-i>%du zepEfb$YSd0a~fG`_5V5*Pl$&6_nG?8J6z%txA8na%A zSKsFeEV`wNq{ z?yAe8jsDa1jE*mRRkr{4o9A}X>#wi+eA-6zVQclm9a7&cPZQpg_P-X_fBy7z_0uH5zDzb56@jBnyM6i>n{+MOoW51; zz~2I#`cOL9b6>khyw_Sf#XXb=^_wW2!{{LtFx7GW9t-T?M+g|r`di~FeCb{&tIyc$cR!(fa^=nO#`PSm+wTut)_Qu`6zj~g^DXx01 ze@!0iJziS8i4~o^u}?spGwc8NU;p}8Etr;cT@C4EeA*MWN3_ePFL{=!ngY+?d;edo z|GRbn&%5vU)&IZuW%4N zm#sftwr9?ITlV|i-QCO%{wbG(bpP^g34FR*m$xv}B2fy0t{wQ2(Z-RnN+)s^#5uCST zANG7a<#bSU&V#goi4y7JGPiuHJ_=N|w!Ab}j$ip>1)peb8msn)4=UA_K2=Mu8OR#V z*@>sO*b1%)F7J>#|83n} zmSsPcE=nXM@E8;;_rA&5!!~izzqzl98?z8OyS@j*(9$TkMzB6f^hF==|}}f!EQP)oaPMWWU$R3ug!YT%f69*b&dSAJ9VuY^M?aXc=^TKJfn6EwCTx)XD7jc%Hl&-K#p-@n`cdf0z&Z?*gC1mlyZzS!8? z$3MHs()!}wp8bhQ%^sI^Hb=H?Zt@e-_1ai#CdKz`LNkL-tl&iDJ1kocuK0Ocr}-1d z!nM~GvL!oJ7(FYk+`Vm9h6gbDp7>F-piXAPom#Q#wS7$s{8;3ex0`C3`W9DLe?KZ7 zf9LMqse%1ceLEs_{QUi%vG88rbo2XP@%WmDOSPVf*KUuyfA?NlY`AmNgrf63=U!dk z#WOwlUE{R)iuSod(I>v>MaWCtcS>B6-y+aHQSo}6ZSAiw|NmXD|B?UizWt>svt|Cy z`0?Sxhx>o$?*A+Sd+AT$HoiOnG{PcR~rTt32I1Mo#gh4KDBw$ z4X?H;Bg^#JwX1e#&pWn$a#7HX2LYP=JiF$1C~}I()Ln5^?qA{?>9;vXum1V=`seX~ z@9*WmJ4X;bx7?HF6_D}P9bLakj;coxyYyAJOyKmn< zy6E(b82bakk2l?WTXwjmxzeri)ypeg3A#%cerPJZVRJTG+)yX;q0p^v$AAqyTU&0= zmq@=XaHx~@^V};-(stjqv$12bH$A3s&;CyS-fNFVT=&=fe5$Z#!TOSp;2C=Y+KwN1 zbA81UC3T77d;NbONL|;sXtvSy_dd{IVnxlD+Q59no-FC$gRCj6fi4XWUzB6-%(P}n zIyy&Yd+sa+_F2K1tGZUc;}aATe7UAVC%g00^~>90-(4&JTbG~demUTV#GPL&c+#Z4 z$V~cByZD1tbw$OF==-|6Q@vh1Un6T=uDLb0dt2x&Rn-aS_E;=3(AHQhpHcYd0lSN? z)pN&3p-P;`Cvos|axFY?o|UWi!z(G<8(VxYo3-lB654qCee`zWwna%hBj(JXt2gcR zy4>alJKnlUe6vHgi3=;URNdgyN!XBi|NC-v_0?Ck^wKD{nUWnJh-ndeuw()WtNd^uiae~t(TKO_tXDCO_$3bOIcrC_#G4%5gq8s zXDAvo_fK80-1D0l#KTd!(DqPq|Rg8Nrmq#@7B|PUG^(GEp%`j;(eH z-|E(HG_G0w@xqnGC3^b)omZY!w6sJ$$jm(?At}?g?@!v!>1P*B&37^iw!Wsl>Beq{ z)GEe@&lOwl{V^y$cucf4TxsvMO}iTE;*%Dz8}6&lnLZ(FP6FR_mhRlb{AqVQ)8tb; zz1n{qoyS+;-tK(-kTmz&9Kk8ObozCVwx2h+!DycUBs*;xOPU4GzqEkpDu-N_N{LJ2 zE8_b2CeCMGblLmLoPHOyI?H^aTgS2{GXU$@0^m5prV_VW+68=MbxvpBhIR(JJr zQBUDg#+Mgtk~dzAi_~kl;#j!U__4<;Hn)De%}=gM9{enjCsTW5U(#;g#_08Yno&G9 zuEw+6|7R^rSg9i8rCsZ1{AhRb#JDfn9cj^CiWOUg^SLG;^_l%PO+Um~`TX4l_Z7nV z8ky4kW|{|Gk7+ia^S<}|SxXt8v&>;`E&@z~$3J$6D#v*ASN^|iBfkFE@Q-r#(&<=&ER*uqx`+reusaa`R$f1vyc4y9P#&! zHOG=Qj~#cfp1?Cn_j-eHrW4mfJ0;IRF%I*hJxu5Pm@2j4# z?yeheYozZZpT|-tW6RmT%AtkHBs0%iK{0FHs-Kk;qGCdNe`~E3o;G!X*G%5P?X!G? zjHVpT=dx!z`oU~&h>204T)*@$vDH^!h5tKf|Ks8O{~zw|-mV|NZ%d*iDdG+d51^0g+K726P z73J9Q)}=Y^MxB$(y>tH!v@g9_yM*i7&ZqJ#oI*qF*8I3XWA=gGg=M>(5|X^G`kOk` z8u040%n&HQAu&Vxl}gma;0T7Z1&&S>=9stXT!S1D++qj2(}g7WEWyo9!1`xB#b^2Bm6+uk7Yqt~2n)HR=9 zmnO)>FW`SlDzVaSiQJ)iyp9vpJ5N4euBK}6c+a6JdeX9or&hZv_c;Hqkel6psXEx{ zxAWERCa1X>Rtw(kZ1m~oP}q{N>a6Lpl9uTq#?Db|553V`I_1~ATKiYG&$!Iy`N`be z_Tj+1xjr*p%5|4sJd!j)Q|-GmSM?H8F_sWZ-%8&rWs$Wio97Aop4`dO%*friIbv^3 zS!H|0PdW2PvM*jdTN$wVQlQ8RJ=RF!cP&R2S8=R5o$#7*)ynn+6ISQ>FEyOk9J+7Z zY*+QH?Ns2`7kO%z!)N48merTLDEv?1mpv=P*$VGXYvu&rIWBNcWd>K@t#1lTJA~G> zTrey@wA0RJ(Mkd5$3C37*SE#4zdG%Na{MfH{RmU5_0O`>BO)p~-$_Z`ewcL3ee;im zI9rQvj!XEX7pEk~>7{m_ENJMB@;DN<(v$bVrlL(;cgy4~YWi9iz53sG_;#qm@~4su ztPZ%S${zW2ROGzEj>%Hr>@K|j-u?8`n=e~D+1G6O!}(Wq-rMl`jIyh4Zj08P)|r#C znr&ep%bHTB!Xh2j&SgKAE;w~AObJb*jGUO{|OG@UfkmzsjlW#1hNio|M*R zrlK&;I+KfBSe`{`-?fufNsWPnoiNX3Sa( z;rPm1QpFl}bxkE7B4tlB?7q7#`}Y6m{Qp06pSPF4tD3UaRiBHGegCs<{TsizZTbFU zw$Or;S}hGqK5Ta*cc`5Rn|njdc+HCY$$5bb&v0<5_9a;a@w`;I-Eh)cOX`|POz6Y^ zB44}N8m7C=`IlXLwod)wg3B8p9`^WUu$;MFEx(Yd)Pc-}mv+;(k3ny>)u)=h;cQzpr{R zZQlLlI*&qW?DYjZ_wKF*O+~+c9j+f=_wQ$a{g1=)|32>jyIp1WwyS$R)vgz{ue|Td zJ-by+bdP)7iL5qBw@shEG3hlGxdd#n)(DQ5OPKs>n$wjd!4E=hl+AQH>U?$`XS4SY zTYdTR<=XwzmmYrk@@0|G|LeY-7xUcjaJD`=FXx`vV72e}6tTOHzI=J}@SkJb-N~0P zPrj)X^*3!~43vu1wy!^H8_XF=Gv3yn8A6BQWL)z!OQ-3{3m=}6C+f1Ts0 z>zUfbxZJ?wj9-)P>rX#zo`0|A=hNxG_puk07XJKl^YZG|tDm2rZ(k1@=Y8%!&!+O% zlaoJ>g4U7T%DZ9TJUPq%+hq0?8y|i9ZJ=l>@m zGQL@IRHY^E`yc+v`!!U1lDFu!)E+Z*w+mcieq+<}jJMODrnnz=U6lFm{rmWRHI?P% z=9k2()s`H8`|a5?v0nB+ff@1#bv)&AO&+eY-O?tcBxr~d2i-{(1;eYpM3ebBs* zIJZT<2IuNsY!Z(is_reaaqDNhefHV2zrU^Tre(}Z+kam=PA+KbX3vJI)VHTA|NVej+u^Y6#U-@kJwCO+QY#wKUm z?c?po&z4X?weLy)i3Uz#U8m;^ta(r$)jI+ zvfqAsR5W491y0U)@7}$8|9xt-a5G zHsD+B`77URuWtpdH;O5Xy{@}!UF??F+h)ACw#}^Jy!2)B-yN>sZ{IE3eKT*{?1$VA z%_b>3e47_WTK(CXIpzPdTRc5(A#d-chI|QP=rIXRU!x|sddd#X*l(Ju%hLR2S#fVU z`ZQILt#wxEUx5?50=k_Z-(T$JcKOb|ySeMvOK1Kx$P`~2rp=aqLGaavjfW%-ONZL5 zJ9uu>zaJKm%S`e_x&P#6TC`n`|jBK>;AFlcgicf7a8Q$wydHI!7V#$KfkM}#i6IP#S{M>GLqC1b+)!a#k zGmN>iBfQnUlBK4jV$TNbOtN+nN< zbMoo;=!-W0XJ?XodyDRj9X&^0YEC@0;%mm6(ut-UX1KBoH_z*Q!spm=UE=iG1(VKj z<(O3P3#jcby!v|XHY3ga8GJx-j^-_Kc9KLu>O);{$U}NhW@NbRbVt z*Pf^BsJKML^!nV1@&9K8Gj6adl3K9Ny@zvIs8`5}5*L2;TTd2lI`dwMg+VD;OZ$KK z9VYn;&2Aan&%T&xJYhwe&K1$0ntd|!J>Fh8|I_tyfXsZyqYe$pBE1ro(*z{`DmjaM zxhs8S-hR!J#5s!-7Q|1oF6I$Ym>l%n^$OF>^n+Y63xEDekt>*SO5uU_WC^}f?gf*W z0=_JbXv_17I5qEE+*K!=^O5%>mT$S$>A$Pt*e7dCZ}II<(hj>Yu|$|Typzv(WbEVX zt?Kn`P3Rf>HmCO@{%Uig7A|~qkYCpD;?@I~Z00RUmz;6t$gJbHrzrF@^oMSkb*$)s zgono3_|p~!YZ%)?+(OQJ{EcN;;W~Sha^YLQPoF!~ckHoXZ&<%kyI=eQpX=v>mKmx~ zBVJwSco*qow4fwJAWe?3D!cco)+NT+^w+s^am;*MuPv4i<-W=t+j4k+EOl((5XQal< zKA5?Nt8xQZiMjq7;RII6XQu6sW>oIfHd&R`mLHRLLTR01&f??7yc+;qt& zXT$m`ANs)Z_mp+XA>lLZA%bqpV+ZAWPLzx z>Iz2N+|q0jwYAI2-swoLtK?J@lTF$6n0eyCiK{qfFwOe?W2U6cWg(H)hqdZQdpz=_ z4}J*T zADk;&$l<_buj4saPE5Pb?NRN|1!fn^Iwjdp7^X<1%x_GbdS+plVxpaYq)qCw$qk98 znr}*J9`OCN&ynR@@1fqFI#s2_$Ok9b`uT#yvg~d&JFz^U(zyTTQoav1lF=D0t<1>_ ztrw~_R9P8Lmfd>$!wusNYxn)xy~{Jk#PZCfxHo~~nUc30mP%}VI_*L4(kV_)j;q*w zVDdP8iLpCadGap#K>726x=c!q7E1NA7MA)>nf^yHbt#Xg;PJ{M!kq4`p_wvIE(jSO z?fRH-AZP94dFs#qw0_*i#bI#ygU;iGU;)jq!AndIc5jSdF7#VtWn@*CXs?bi@5UOr z#mhEp3Ru-uF3K{=FS(SXIBo8O|FV^fm4c2MkhKJ9N5?> zv{`D-bGM5-E6?0N{_Eg`mc6aDa)QTXcJO9=+S55XSy!s$nvz`02Q^0lk+`^2ZSSy%)3n|Ne(y=)pQ#au#u1%)ZiXbo%BO{nFm_k372EyS30f7uHK8;QkwVN#qY`}i;2Pbu0}vUBEguPsqWo0jy1Z%Sk; zRyzIDrA6u4fp6_Wj*9hC{q7>3d}lc(X(p}w71oiHW)v9Bpq(1yF3(Z;nd67!L-s$n z%QTm~ozAl}QDgBj=8`!{%~u*uEEHL(Q*=y`RcdAYk|XPFBDhjtXkTqfw(78*DLD7D zSU8`$)XXK%WOZifJ?VY&>hc=9T?x+ZPu=w$y>mBy;IHJ{;gi4kTuZ`^3%3rqzue&w zt+w{@^5-^!TZ2Q7*Sc}-lCc(>I?0#gq z@lp!2exU5mjYr;Qy5v3*_^s<;+_FR=;FyB3h1++VuKnv~2%OjTxgocM{hjKwlTMSB z-_11+br9YIZ`Puw=Z1PxgLY|@OJFiP}wrb4bdHzy0kDttVr*X-3 z>D(-7V?W0|*AA$tb6vk8sCCZD{*Y~RnlMCqFZtv^OQIFvtO}xZu!92dcR?j ztx){;JU9%$m<0vd!(m!`K_>7tDh((?ZWmWqUD9C!}3qAN3boA|io8{U|iPLOTR zQ_l)&eE8XE&VKjzyK@#ST0UvThwhNQ>X#oaT_m?#sPo>JElZ5&&d?E`%ke|(UP1R# z&*K)EDQn(zIeuc$()|9D@5zIJb020$nu|(SFFYc9^!cToHF*Ro3%GrCtyPB>)KQ@!%orHsbR-f7HnKawvQ7V)U3O^LkDrVuQAR?0P0X3+$Z z20liP_ye^kL=LmJ&Mmu;#9{bna;7~eir+-cux=WNDg7eEGZk z(!vuQF-@oUa(zGdDd$Z|PV+wIrgK{#W@g9sohvajUOeI6M4og9bCB}dYef+bqQ6;~Wfz#R-AvR1C7q2=uFCb)w)?b@_5ougc70z{T=ap!7 zy!)`X+apteQGK7`@pX&%xXv!WD0KA3AJKd=Uthd5OV(aHru9k8!NO}7H^$)!zCwC-2EY+ zf0nBKRhQL{`z6MdN*7K~?n4yDz`p@pkIX}4=3uRc}AI@-iG3oUR$ykd5 zyFX^i6J@-#H(4x}Zd!bA{=bHAl3cdzbJe4G^j~jxnc#QiZ=z=&i_z_rmDUf0LIqC? z&Z*&%JGk-n(}3V`JGO@+`5(k3T|Wmc7G)AKJ9x~VN9h-z@7@)9omX@v`0~YlLMB`` z{vGU~Xt!*pIopOUUWV7x9=Y)DUMegb+^@OQ$R|vB1N-+U_RUjT>rSap{W5+2j3W;< zRrqV3&+=?37N6i&xli@r0zvI7Y+v5bRNh-YrT9vH>nWoXsX-+o>79lxxxYGJI(^>l ze$sVu8B^xl*{q+MzncA)?kZvUFkSLb`oZ=~v(Fq#=4ll7FmY@)fkH&*OoKw)Z>u(Z5by>rZ$85dKGr^v_~YW>}i zFSWIRAtQ=yEwf`u6WjG(hVA7lnGbgz@8AzEu(@8lo+0kalszwb&eYiYYIV=@l9=&0 zPpkXl%KTh zic%`hn$&tX!0_ghy3Yce+ytfua(S4V^8N2xpyTTjIMwb-#GxNk&n0;|H?#;Am|Cq6 zRb5;dk^4)*_LR-Mn4{1aDF_jYZsJ^76dBxG3d&}}AZ(BZzaZR}_$!U7Q z^i{R#G2?dMzZxY9+&7N>t6nIz(8x2z@@A=yf>ik~n@tiOvWq9WXdn3}{3n1R&^?N! zWWlW42`@E{9-MWyWi{7A1|yBlr_TE==HKz*^56fi%mK?4*4Rf}lXKL1e(R*bGrK>F z?Hi(7n`Jkr%rbDiK6~oZ2g#vNr8e`aA6AR`Fk5hq{f+m|JO8JKKWLw+b?f7mo%&U0 ztRD(q4}R}EMdsw9yXPaOcV@DsJ8fVVoIZ8w_N**6Ic*NrKfgb0{k|exFj+#WyTN;t zhx@~pl_v$JPE)Zf*e*9^m4#f=#S?EBS7@c&uBs7c+gCjI_azO*;5C*D#Xe2^x4G(+ z^wVn-_w4sGnxMigsa1Jlorg%9rqg!IFN~tEtjk`fx!hUE+*QKUse9lioA|M9n+=<% zJ-b%SzxlV*r^^=vCRhtE4a}@vn5ed3V@1YU_U|Rp9(kXR=)_5#- zXFiNEwp9A~WZ{+Y$L?!V;(6>D4JPRDnRWFUJGe#c3-=GZve@7E>&3s(9_JgROfEm1 zZYbp^R*;ap!M**F!n?@_AH?;hRK7_S-2*8`$LM_JtS5Twyy} zm%6Lw%Gs+{Z#Najg+vLxKE^%y%Cb{uc~97}>t0g-n0R4r-W1Osr&&RF-8cBA#CACB zGu*vE$;n~n-B-37`;Rtb=j610=`<89!GC=UUWd5!z`CU{PtlLqt>LA z4;&+2E`K89SP+u8@3Cq&si=j<9y`Df$8xMwh!zzw!P4}7c)I3$;r!g7{ zc&*gjv6Eq$P`;vFMUg?cbc0s7>B1SF8qa@darOvWc^$F${aVE6;~=ze-{jOQciIY@ z^|^GGmNs4bw`KL$6#^j#lOqr2?Pa>b*m6U9drii5t?=pY>trO(Y@hJ1^NhIO?iFvM zm&?jJ+Ae%%s1-P+@4o$2)-Av08k)>}ws4Jz$T~Lm1>%?1ZMoT^2=LH*Va$ zthV`rvqeiNDj&Ph@`_xpc!SA(f^nJx9%?R;Q;IPE(P6 zm)F#O#N>#Jy73~VlCr&U7TW2!$z6ustwvxyG z(vri^9&PxtRM5KF&yj!XiQ`U;Jt98L&+m$^Hn2$ah!A#_+Oj=EiskyL)|s92(wc*_ zQeK~)@4wTQ>*|qD>f)~**fvLQe{;F9h+~2r+j8aY0UWtcznM!;In5W@@5(dfZI3|d z%nSTM=93q$?U?)~^YjnK(Bqk3W54>n{ABuY`az-3vHw*wwnuu-pP|Xtw#U$Sp<>^Z zOA+0VR!qt}#V_K*euYV>d-FclYqF6RZ)P`ex`s8Jnz3k|^hekK(=N_fTJlBertL#F zXWsr*JEw&N&pTq%ADlWX(E0mRo`sX9E{K?NQe;)jL(v%~IuTc^UyED)QI@=1z0pHy zVezi--G%v=KR0$=w*GSP;SH5DJH*9{kIuZ_`gqgnj%fA2t`oUD`=aGs)OdV<9d&Hz z__Fo+*8YtAWfsnl3)o%>aH%f;*;run@Q0VwN71$=PiVPKtd%(;b4&d{w( z>uG;U5}QZU@goP4XS@EBR-P?;BsEK`GFUn9;YC5w29ehy8%ur}F)dv<$>$bxH_sj> z-)DZ>&M8(kyE2yKR9}=~er6$&TDyo-Ugf|3VS`(Dg!{exf3Z&ZX>ZcG-Bfw@GmDHx z_M0VU><+prwPcT{(VdLeK962`tvdGZIS&qI_pQ99a*$^;$5tij>R=Uwf!$*VG0plPgKO-*hHVSlYy0H8FT`-kg*T$6^`+ zXSw^VYY$lOq}6**SwhC$uQ}-CM~}5<7O=)WSZiW+&|d64r^5RO(>iWuHkG}eR=tSF zS@Y38yTI2x8-7h+I=@w^EL9s41KpLdh@-u^?YpBn4!9> zZ`HKDUxoS?tW4R=P*CvOO;}Rx@LWFqw8KZ3D{5Qb8XOT5^xSnRQuWC*5v@5#N~R>S zEncCw?Z}P0WnQj%*IJX~rzi$Yn{Dte^GsaXisS;1=A~&L*6!>X!&RsBmseCgdnEN&7gua{Ve|ga7oaWS-Vn{RV5!h^ z#)%8P{TN=bU&_4Y-mGcLDb#*_?diVQXI#(omYnX)jFUQ;DDa9gVDc1(SLbD(Ph?)o z_+vtDS<4oWc4wUjk(ZA$E?<$-xMX4~x8 zDVNWfB{e-%*(y14spS;jsWxFd3Z}mND!lXv|8;idRmq07Muve*%>@cN{p$SP0>>M+ zPvj_9Sad2{ppoaaty!o1ISrTHdZ%7|d3I^Tgyk1!vs;LVwcYQw5s;Z{9+$Z-WZ%x$ z3->eLzrImcrSFq>LeI&YTPHXv1Zk7Ab=*Md9b{Qdu+b{!5MkeNn)4nSsYb2q-I@V=28+$nku3H_%w$@gSo2xoa4d;1<_w>Pbf3% zh%Ic@vzx)Ub@nTn+QKhNGUCZe^M!)5CP;N`yxeSh#<6ABf<5sGw{{%xYd+$7G5Dlq zo6!gMJQg*H!*l05OnAM?tnl~?sl(SbtQrNHj`N9^@84pgyR6WpH&Efof(c$Vv$Ymp zS-(RsRO|7RnBQ~u^m1?oG*&FDn>q7?;4ZE|i#D&yS}|Xw<R zb!QYABkg}rWRln-miEnOe(uD>NoDzt3h!rq{TEXo{v*e_sb&4o?3(iVfroqVE@z6C zp892_p@gSZ)(^H@Y>U4XPdT~Z_75|of-v*$AFdOZp4L!4`=xPi;6>>*r4C1AOtdZD z21uvzy;;o3fl0v<R>ozJZCVY@c-ic3lB{S?Efn;vOv@)DMbXOx~@Atd~@X6YH{#TReScr;fj zGf}2=lcI%k;4ArEWw#$z96w;=d}Pay%bRZVRT?~M=&-W>waPfR-Ey*oj;hIF`OLNXz^P@vw<#pzK&)JR)921#yo5Qm`Tw}Q(wj{)} zTwWNN8@|L-vod_irwcp66u$Q_h|cia>GzTSZKtca^wJnd4NjGRQcW+?UFP)|sV#e) z95(+mtMH3IcS?6(DOziMrEiixht{`!XCCk@n%90?Fw!-_jlX)P(X`EXX1?xrxEOW5 zNn(rN%WoPR=PP`htT=n$g@C}l;u~E&wYkCre7H8o+b-o1#a4{3{roEKR{w^@uOA%L6XiQ3yQQb$R;-`QDv^5@ zFBZhO9F*($bJ3|*Ug~g1d&@nYk1Dc_KG{vwe!avy=jE#zSNG4^@?K`& z)BR6A?^ijbdSybwCyo63?Mye8T`xWucB=3FNr6{g(|tG{1fGYuAKaGAmKpQ<)96?YcK{>lZ$s zusTjuQs}srS5>zn2g6a0#f$k3x7BOdL}>MIVLsHQu~KEjCt=5v(o?-Op3K^~EHGiq zS--HPI51$x*@6;5}x<-VFOI@Ui}D|w e_x}H9V-UPow({;7iJ1%x3=E#GelF{r5}E)Et)wFW literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp new file mode 100644 index 00000000..137803bd --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.cpp @@ -0,0 +1,658 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 12 device and swapchain +// + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +namespace +{ + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) : + m_backBufferIndex(0), + m_fenceValues{}, + m_rtvDescriptorSize(0), + m_screenViewport{}, + m_scissorRect{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_d3dMinFeatureLevel(minFeatureLevel), + m_window(0), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_11_0), + m_rotation(DXGI_MODE_ROTATION_IDENTITY), + m_outputSize{0, 0, 1, 1}, + m_orientationTransform3D(ScreenRotation::Rotation0), + m_deviceNotify(nullptr) +{ + if (backBufferCount > MAX_BACK_BUFFER_COUNT) + { + throw std::out_of_range("backBufferCount too large"); + } + + if (minFeatureLevel < D3D_FEATURE_LEVEL_11_0) + { + throw std::out_of_range("minFeatureLevel too low"); + } +} + +// Destructor for DeviceResources. +DX::DeviceResources::~DeviceResources() +{ + // Ensure that the GPU is no longer referencing resources that are about to be destroyed. + WaitForGpu(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ +#if defined(_DEBUG) + // Enable the debug layer (only available if the Graphics Tools feature-on-demand is enabled). + { + ComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf())))) + { + debugController->EnableDebugLayer(); + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } + + ComPtr dxgiInfoQueue; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf())))) + { + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); + dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); + } + } +#endif + + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(m_dxgiFactory.ReleaseAndGetAddressOf()))); + + ComPtr adapter; + GetAdapter(adapter.GetAddressOf()); + + // Create the DX12 API device object. + DX::ThrowIfFailed(D3D12CreateDevice( + adapter.Get(), + m_d3dMinFeatureLevel, + IID_PPV_ARGS(m_d3dDevice.ReleaseAndGetAddressOf()) + )); + +#ifndef NDEBUG + // Configure debug device (if active). + ComPtr d3dInfoQueue; + if (SUCCEEDED(m_d3dDevice.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D12_MESSAGE_ID hide[] = + { + D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, + D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + }; + D3D12_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } +#endif + + // Determine maximum supported feature level for this device + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + }; + + D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels = + { + _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0 + }; + + HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featLevels, sizeof(featLevels)); + if (SUCCEEDED(hr)) + { + m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel; + } + else + { + m_d3dFeatureLevel = m_d3dMinFeatureLevel; + } + + // Create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.ReleaseAndGetAddressOf()))); + + // Create descriptor heaps for render target views and depth stencil views. + D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {}; + rtvDescriptorHeapDesc.NumDescriptors = m_backBufferCount; + rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvDescriptorHeapDesc, IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf()))); + + m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12_DESCRIPTOR_HEAP_DESC dsvDescriptorHeapDesc = {}; + dsvDescriptorHeapDesc.NumDescriptors = 1; + dsvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + + DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvDescriptorHeapDesc, IID_PPV_ARGS(m_dsvDescriptorHeap.ReleaseAndGetAddressOf()))); + } + + // Create a command allocator for each back buffer that will be rendered to. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(m_commandAllocators[n].ReleaseAndGetAddressOf()))); + } + + // Create a command list for recording graphics commands. + DX::ThrowIfFailed(m_d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[0].Get(), nullptr, IID_PPV_ARGS(m_commandList.ReleaseAndGetAddressOf()))); + DX::ThrowIfFailed(m_commandList->Close()); + + // Create a fence for tracking GPU execution progress. + DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_backBufferIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + m_fenceValues[m_backBufferIndex]++; + + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Wait until all previous GPU work is complete. + WaitForGpu(); + + // Release resources that are tied to the swap chain and update fence values. + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_renderTargets[n].Reset(); + m_fenceValues[n] = m_fenceValues[m_backBufferIndex]; + } + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + // If the swap chain already exists, resize it, otherwise create one. + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Create a descriptor for the swap chain. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // Create a swap chain for the window. + ComPtr swapChain; + DX::ThrowIfFailed(m_dxgiFactory->CreateSwapChainForCoreWindow( + m_commandQueue.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&m_swapChain)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Obtain the back buffers for this window which will be the final render targets + // and create render target views for each of them. + for (UINT n = 0; n < m_backBufferCount; n++) + { + DX::ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(m_renderTargets[n].GetAddressOf()))); + + wchar_t name[25] = {}; + swprintf_s(name, L"Render target %u", n); + m_renderTargets[n]->SetName(name); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = m_backBufferFormat; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), n, m_rtvDescriptorSize); + m_d3dDevice->CreateRenderTargetView(m_renderTargets[n].Get(), &rtvDesc, rtvDescriptor); + } + + // Reset the index to the current back buffer. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Allocate a 2-D surface as the depth/stencil buffer and create a depth/stencil view + // on this surface. + CD3DX12_HEAP_PROPERTIES depthHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC depthStencilDesc = CD3DX12_RESOURCE_DESC::Tex2D( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1 // Use a single mipmap level. + ); + depthStencilDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; + depthOptimizedClearValue.Format = m_depthBufferFormat; + depthOptimizedClearValue.DepthStencil.Depth = 1.0f; + depthOptimizedClearValue.DepthStencil.Stencil = 0; + + DX::ThrowIfFailed(m_d3dDevice->CreateCommittedResource( + &depthHeapProperties, + D3D12_HEAP_FLAG_NONE, + &depthStencilDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &depthOptimizedClearValue, + IID_PPV_ARGS(m_depthStencil.ReleaseAndGetAddressOf()) + )); + + m_depthStencil->SetName(L"Depth stencil"); + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = m_depthBufferFormat; + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + + m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + // Set the 3D rendering viewport and scissor rectangle to target the entire window. + m_screenViewport.TopLeftX = m_screenViewport.TopLeftY = 0.f; + m_screenViewport.Width = static_cast(backBufferWidth); + m_screenViewport.Height = static_cast(backBufferHeight); + m_screenViewport.MinDepth = D3D12_MIN_DEPTH; + m_screenViewport.MaxDepth = D3D12_MAX_DEPTH; + + m_scissorRect.left = m_scissorRect.top = 0; + m_scissorRect.right = backBufferWidth; + m_scissorRect.bottom = backBufferHeight; +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size. +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc.left == m_outputSize.left + && newRc.top == m_outputSize.top + && newRc.right == m_outputSize.right + && newRc.bottom == m_outputSize.bottom + && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + for (UINT n = 0; n < m_backBufferCount; n++) + { + m_commandAllocators[n].Reset(); + m_renderTargets[n].Reset(); + } + + m_depthStencil.Reset(); + m_commandQueue.Reset(); + m_commandList.Reset(); + m_fence.Reset(); + m_rtvDescriptorHeap.Reset(); + m_dsvDescriptorHeap.Reset(); + m_swapChain.Reset(); + m_d3dDevice.Reset(); + m_dxgiFactory.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Prepare the command list and render target for rendering. +void DX::DeviceResources::Prepare() +{ + // Reset command list and allocator. + DX::ThrowIfFailed(m_commandAllocators[m_backBufferIndex]->Reset()); + DX::ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_backBufferIndex].Get(), nullptr)); + + // Transition the render target into the correct state to allow for drawing into it. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); + m_commandList->ResourceBarrier(1, &barrier); +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + // Transition the render target to the state that allows it to be presented to the display. + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_backBufferIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); + m_commandList->ResourceBarrier(1, &barrier); + + // Send the command list off to the GPU for processing. + DX::ThrowIfFailed(m_commandList->Close()); + m_commandQueue->ExecuteCommandLists(1, CommandListCast(m_commandList.GetAddressOf())); + + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present(1, 0); + + // If the device was reset we must completely reinitialize the renderer. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + + MoveToNextFrame(); + } +} + +// Wait for pending GPU work to complete. +void DX::DeviceResources::WaitForGpu() noexcept +{ + if (m_commandQueue && m_fence && m_fenceEvent.IsValid()) + { + // Schedule a Signal command in the GPU queue. + UINT64 fenceValue = m_fenceValues[m_backBufferIndex]; + if (SUCCEEDED(m_commandQueue->Signal(m_fence.Get(), fenceValue))) + { + // Wait until the Signal has been processed. + if (SUCCEEDED(m_fence->SetEventOnCompletion(fenceValue, m_fenceEvent.Get()))) + { + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + + // Increment the fence value for the current frame. + m_fenceValues[m_backBufferIndex]++; + } + } + } +} + +// Prepare to render the next frame. +void DX::DeviceResources::MoveToNextFrame() +{ + // Schedule a Signal command in the queue. + const UINT64 currentFenceValue = m_fenceValues[m_backBufferIndex]; + DX::ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue)); + + // Update the back buffer index. + m_backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + + // If the next frame is not ready to be rendered yet, wait until it is ready. + if (m_fence->GetCompletedValue() < m_fenceValues[m_backBufferIndex]) + { + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_backBufferIndex], m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Set the fence value for the next frame. + m_fenceValues[m_backBufferIndex] = currentFenceValue + 1; +} + +// This method acquires the first available hardware adapter that supports Direct3D 12. +// If no such adapter can be found, try WARP. Otherwise throw an exception. +void DX::DeviceResources::GetAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + DX::ThrowIfFailed(adapter->GetDesc1(&desc)); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), m_d3dMinFeatureLevel, _uuidof(ID3D12Device), nullptr))) + { +#ifdef _DEBUG + wchar_t buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + break; + } + } + +#if !defined(NDEBUG) + if (!adapter) + { + // Try WARP12 instead + if (FAILED(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf())))) + { + throw std::exception("WARP12 not available. Enable the 'Graphics Tools' feature-on-demand"); + } + + OutputDebugStringA("Direct3D Adapter - WARP12\n"); + } +#endif + + if (!adapter) + { + throw std::exception("No Direct3D 12 device found"); + } + + *ppAdapter = adapter.Detach(); +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h new file mode 100644 index 00000000..086d0cec --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/DeviceResources.h @@ -0,0 +1,117 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT, + UINT backBufferCount = 2, + D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0); + ~DeviceResources(); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Prepare(); + void Present(); + void WaitForGpu() noexcept; + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D12Device* GetD3DDevice() const { return m_d3dDevice.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D12Resource* GetRenderTarget() const { return m_renderTargets[m_backBufferIndex].Get(); } + ID3D12Resource* GetDepthStencil() const { return m_depthStencil.Get(); } + ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } + ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocators[m_backBufferIndex].Get(); } + ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D12_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + D3D12_RECT GetScissorRect() const { return m_scissorRect; } + UINT GetCurrentFrameIndex() const { return m_backBufferIndex; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_backBufferIndex, m_rtvDescriptorSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + } + + private: + void MoveToNextFrame(); + void GetAdapter(IDXGIAdapter1** ppAdapter); + + const static size_t MAX_BACK_BUFFER_COUNT = 3; + + UINT m_backBufferIndex; + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_commandQueue; + Microsoft::WRL::ComPtr m_commandList; + Microsoft::WRL::ComPtr m_commandAllocators[MAX_BACK_BUFFER_COUNT]; + + // Swap chain objects. + Microsoft::WRL::ComPtr m_dxgiFactory; + Microsoft::WRL::ComPtr m_swapChain; + Microsoft::WRL::ComPtr m_renderTargets[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::ComPtr m_depthStencil; + + // Presentation fence objects. + Microsoft::WRL::ComPtr m_fence; + UINT64 m_fenceValues[MAX_BACK_BUFFER_COUNT]; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Direct3D rendering objects. + Microsoft::WRL::ComPtr m_rtvDescriptorHeap; + Microsoft::WRL::ComPtr m_dsvDescriptorHeap; + UINT m_rtvDescriptorSize; + D3D12_VIEWPORT m_screenViewport; + D3D12_RECT m_scissorRect; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + DXGI_MODE_ROTATION m_rotation; + RECT m_outputSize; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/LambertPS.hlsl b/Samples/IntroGraphics/SimpleLightingUWP12/LambertPS.hlsl new file mode 100644 index 00000000..62b916fd --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/LambertPS.hlsl @@ -0,0 +1,2 @@ +// LambertPS.hlsl file to provide an MSBuild target for the LambertPS pixel-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp new file mode 100644 index 00000000..1aa89823 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/Main.cpp @@ -0,0 +1,357 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLightingUWP12.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_sample->OnSuspending(); + + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + HandleWindowSizeChanged(); + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + m_sample->OnActivated(); + else + m_sample->OnDeactivated(); + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + +private: + bool m_exit; + bool m_visible; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Package.appxmanifest b/Samples/IntroGraphics/SimpleLightingUWP12/Package.appxmanifest new file mode 100644 index 00000000..29f28984 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + SimpleLightingUWP12 + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx b/Samples/IntroGraphics/SimpleLightingUWP12/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..a3302a66cbccabf5cb9a2b57e2cf525dd94880ba GIT binary patch literal 80978 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 literal 0 HcmV?d00001 diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLighting.hlsli b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLighting.hlsli new file mode 100644 index 00000000..90eed8cd --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLighting.hlsli @@ -0,0 +1,80 @@ +//-------------------------------------------------------------------------------------- +// SimpleLighting.hlsl +// +// Shader demonstrating Lambertian lighting from multiple sources +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// Constant Buffer Variables +//-------------------------------------------------------------------------------------- +cbuffer Constants : register( b0 ) +{ + float4x4 mWorld; + float4x4 mView; + float4x4 mProjection; + float4 lightDir[ 2 ]; + float4 lightColor[ 2 ]; + float4 outputColor; +}; + + +//-------------------------------------------------------------------------------------- +struct VS_INPUT +{ + float4 Pos : POSITION; + float3 Normal : NORMAL; +}; + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float3 Normal : TEXCOORD0; +}; + + +//-------------------------------------------------------------------------------------- +// Name: TriangleVS +// Desc: Vertex shader +//-------------------------------------------------------------------------------------- +PS_INPUT TriangleVS( VS_INPUT input ) +{ + PS_INPUT output = ( PS_INPUT )0; + output.Pos = mul( input.Pos, mWorld ); + output.Pos = mul( output.Pos, mView ); + output.Pos = mul( output.Pos, mProjection ); + output.Normal = mul( input.Normal, ( ( float3x3 ) mWorld ) ); + + return output; +} + + +//-------------------------------------------------------------------------------------- +// Name: TrianglePS +// Desc: Pixel shader applying Lambertian lighting from two lights +//-------------------------------------------------------------------------------------- +float4 LambertPS( PS_INPUT input ) : SV_Target +{ + float4 finalColor = 0; + + //do NdotL lighting for 2 lights + for( int i=0; i< 2; i++ ) + { + finalColor += saturate( dot( ( float3 ) lightDir[ i ], input.Normal ) * lightColor[ i ] ); + } + finalColor.a = 1; + return finalColor; +} + + +//-------------------------------------------------------------------------------------- +// Name: TriangleSolidColorPS +// Desc: Pixel shader applying solid color +//-------------------------------------------------------------------------------------- +float4 SolidColorPS( PS_INPUT input ) : SV_Target +{ + return outputColor; +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp new file mode 100644 index 00000000..4b827d32 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.cpp @@ -0,0 +1,582 @@ +//-------------------------------------------------------------------------------------- +// SimpleLightingUWP12.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "SimpleLightingUWP12.h" + +#include "ATGColors.h" +#include "ReadData.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ + struct Vertex + { + XMFLOAT3 pos; + XMFLOAT3 normal; + }; +} + +Sample::Sample() + : m_mappedConstantData(nullptr) + , m_constantDataGpuAddr(0) + , m_curRotationAngleRad(0.0f) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + m_deviceResources->RegisterDeviceNotify(this); +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); + m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + float elapsedTime = float(timer.GetElapsedSeconds()); + + // Update the rotation constant + m_curRotationAngleRad += elapsedTime / 3.f; + if (m_curRotationAngleRad >= XM_2PI) + { + m_curRotationAngleRad -= XM_2PI; + } + + // Rotate the cube around the origin + XMStoreFloat4x4(&m_worldMatrix, XMMatrixRotationY(m_curRotationAngleRad)); + + // Setup our lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Rotate the second light around the origin + XMMATRIX rotate = XMMatrixRotationY(-2.0f * m_curRotationAngleRad); + XMVECTOR lightDir = XMLoadFloat4(&m_lightDirs[1]); + lightDir = XMVector3Transform(lightDir, rotate); + XMStoreFloat4(&m_lightDirs[1], lightDir); + + // Handle controller input for exit + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + // Check to see if the GPU is keeping up + int frameIdx = m_deviceResources->GetCurrentFrameIndex(); + int numBackBuffers = m_deviceResources->GetBackBufferCount(); + uint64_t completedValue = m_fence->GetCompletedValue(); + if ((frameIdx > completedValue) // if frame index is reset to zero it may temporarily be smaller than the last GPU signal + && (frameIdx - completedValue > numBackBuffers)) + { + // GPU not caught up, wait for at least one available frame + DX::ThrowIfFailed(m_fence->SetEventOnCompletion(frameIdx - numBackBuffers, m_fenceEvent.Get())); + WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE); + } + + // Prepare the command list to render a new frame. + m_deviceResources->Prepare(); + Clear(); + + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render"); + + // Index into the available constant buffers based on the number + // of draw calls. We've allocated enough for a known number of + // draw calls per frame times the number of back buffers + unsigned int constantBufferIndex = c_numDrawCalls * (frameIdx % numBackBuffers); + + // Set the root signature and pipeline state for the command list + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + commandList->SetPipelineState(m_lambertPipelineState.Get()); + + // Set the per-frame constants + ConstantBuffer sceneParameters = {}; + + // Shaders compiled with default row-major matrices + sceneParameters.worldMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_worldMatrix)); + sceneParameters.viewMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_viewMatrix)); + sceneParameters.projectionMatrix = XMMatrixTranspose(XMLoadFloat4x4(&m_projectionMatrix)); + + sceneParameters.lightDir[0] = XMLoadFloat4(&m_lightDirs[0]); + sceneParameters.lightDir[1] = XMLoadFloat4(&m_lightDirs[1]); + sceneParameters.lightColor[0] = XMLoadFloat4(&m_lightColors[0]); + sceneParameters.lightColor[1] = XMLoadFloat4(&m_lightColors[1]); + sceneParameters.outputColor = XMLoadFloat4(&m_outputColor); + + // Set the constants for the first draw call + memcpy(&m_mappedConstantData[constantBufferIndex].constants, &sceneParameters, sizeof(ConstantBuffer)); + + // Bind the constants to the shader + auto baseGpuAddress = m_constantDataGpuAddr + sizeof(PaddedConstantBuffer) * constantBufferIndex; + commandList->SetGraphicsRootConstantBufferView(c_rootParameterCB, baseGpuAddress); + + // Set up the input assembler + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); + commandList->IASetIndexBuffer(&m_indexBufferView); + + // Draw the Lambert lit cube + commandList->DrawIndexedInstanced(36, 1, 0, 0, 0); + baseGpuAddress += sizeof(PaddedConstantBuffer); + ++constantBufferIndex; + + // Render each light + commandList->SetPipelineState(m_solidColorPipelineState.Get()); + + for (int m = 0; m < 2; ++m) + { + XMMATRIX lightMatrix = XMMatrixTranslationFromVector(5.0f * sceneParameters.lightDir[m]); + XMMATRIX lightScaleMatrix = XMMatrixScaling(0.2f, 0.2f, 0.2f); + lightMatrix = lightScaleMatrix * lightMatrix; + + // Update the world variable to reflect the current light + sceneParameters.worldMatrix = XMMatrixTranspose(lightMatrix); + sceneParameters.outputColor = sceneParameters.lightColor[m]; + + // Set the constants for the draw call + memcpy(&m_mappedConstantData[constantBufferIndex].constants, &sceneParameters, sizeof(ConstantBuffer)); + + // Bind the constants to the shader + commandList->SetGraphicsRootConstantBufferView(c_rootParameterCB, baseGpuAddress); + + commandList->DrawIndexedInstanced(36, 1, 0, 0, 0); + baseGpuAddress += sizeof(PaddedConstantBuffer); + ++constantBufferIndex; + } + + PIXEndEvent(commandList); + + // Show the new frame. + PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + + // GPU will signal an increasing value each frame + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), frameIdx); + + PIXEndEvent(m_deviceResources->GetCommandQueue()); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto commandList = m_deviceResources->GetCommandList(); + PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto rtvDescriptor = m_deviceResources->GetRenderTargetView(); + auto dsvDescriptor = m_deviceResources->GetDepthStencilView(); + + commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor); + commandList->ClearRenderTargetView(rtvDescriptor, ATG::ColorsLinear::Background, 0, nullptr); + commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); + + // Set the viewport and scissor rect. + auto viewport = m_deviceResources->GetScreenViewport(); + auto scissorRect = m_deviceResources->GetScissorRect(); + commandList->RSSetViewports(1, &viewport); + commandList->RSSetScissorRects(1, &scissorRect); + + PIXEndEvent(commandList); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + auto device = m_deviceResources->GetD3DDevice(); + + // Create a root signature with one constant buffer view + { + CD3DX12_ROOT_PARAMETER rp = {}; + rp.InitAsConstantBufferView(c_rootParameterCB, 0); + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + rootSignatureDesc.Init(1, &rp, 0, nullptr, + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT + | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS + | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS); + + ComPtr signature; + ComPtr error; + HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); + if (FAILED(hr)) + { + if (error) + { + OutputDebugStringA(reinterpret_cast(error->GetBufferPointer())); + } + throw DX::com_exception(hr); + } + + DX::ThrowIfFailed( + device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); + } + + // Create the constant buffer memory and map the CPU and GPU addresses + { + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + size_t cbSize = c_numDrawCalls * m_deviceResources->GetBackBufferCount() * sizeof(PaddedConstantBuffer); + + const D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(cbSize); + DX::ThrowIfFailed(device->CreateCommittedResource( + &uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &constantBufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(m_perFrameConstants.GetAddressOf()))); + DX::ThrowIfFailed(m_perFrameConstants->SetName(L"Per Frame CB")); + + DX::ThrowIfFailed(m_perFrameConstants->Map(0, nullptr, reinterpret_cast< void** >(&m_mappedConstantData))); + + m_constantDataGpuAddr = m_perFrameConstants->GetGPUVirtualAddress(); + } + + // Load the shader blob for the vertex shader that will be shared by two pipeline state objects + { + auto triangleVSBlob = DX::ReadData(L"TriangleVS.cso"); + + // Input element descriptor also shared by two pipeline state objects + static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + // Create the Pipelline State Object for the Lambert pixel shader + { + auto lambertPSBlob = DX::ReadData(L"LambertPS.cso"); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(triangleVSBlob.data(), triangleVSBlob.size()); + psoDesc.PS = CD3DX12_SHADER_BYTECODE(lambertPSBlob.data(), lambertPSBlob.size()); + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_PPV_ARGS(m_lambertPipelineState.ReleaseAndGetAddressOf()))); + } + + // Create the Pipeline State Object for the solid color pixel shader + { + auto solidColorPSBlob = DX::ReadData(L"SolidColorPS.cso"); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(triangleVSBlob.data(), triangleVSBlob.size()); + psoDesc.PS = CD3DX12_SHADER_BYTECODE(solidColorPSBlob.data(), solidColorPSBlob.size()); + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); + psoDesc.SampleDesc.Count = 1; + DX::ThrowIfFailed( + device->CreateGraphicsPipelineState(&psoDesc, + IID_PPV_ARGS(m_solidColorPipelineState.ReleaseAndGetAddressOf()))); + } + } + + // Create the vertex buffer + { + static const Vertex vertices[] = + { + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, + + { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, + }; + + // Note: using upload heaps to transfer static data like vert buffers is not + // recommended. Every time the GPU needs it, the upload heap will be marshalled + // over. Please read up on Default Heap usage. An upload heap is used here for + // code simplicity and because there are very few verts to actually transfer. + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(vertices)); + DX::ThrowIfFailed( + device->CreateCommittedResource(&uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the vertex buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_vertexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, vertices, sizeof(vertices)); + m_vertexBuffer->Unmap(0, nullptr); + + // Initialize the vertex buffer view. + m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView.StrideInBytes = sizeof(Vertex); + m_vertexBufferView.SizeInBytes = sizeof(vertices); + } + + // Create the index buffer + { + static const uint16_t indices[] = + { + 3,1,0, + 2,1,3, + + 6,4,5, + 7,4,6, + + 11,9,8, + 10,9,11, + + 14,12,13, + 15,12,14, + + 19,17,16, + 18,17,19, + + 22,20,21, + 23,20,22 + }; + + // See note above + const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(indices)); + DX::ThrowIfFailed( + device->CreateCommittedResource(&uploadHeapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(m_indexBuffer.ReleaseAndGetAddressOf()))); + + // Copy the data to the index buffer. + UINT8* pVertexDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. + DX::ThrowIfFailed( + m_indexBuffer->Map(0, &readRange, reinterpret_cast(&pVertexDataBegin))); + memcpy(pVertexDataBegin, indices, sizeof(indices)); + m_indexBuffer->Unmap(0, nullptr); + + // Initialize the index buffer view. + m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); + m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; + m_indexBufferView.SizeInBytes = sizeof(indices); + } + + // Wait until assets have been uploaded to the GPU. + m_deviceResources->WaitForGpu(); + + // Create a fence for synchronizing between the CPU and the GPU + DX::ThrowIfFailed(device->CreateFence(m_deviceResources->GetCurrentFrameIndex(), D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf()))); + + // Initialize the world matrix + XMStoreFloat4x4(&m_worldMatrix, XMMatrixIdentity()); + + // Initialize the view matrix + static const XMVECTORF32 c_eye = { 0.0f, 4.0f, -10.0f, 0.0f }; + static const XMVECTORF32 c_at = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const XMVECTORF32 c_up = { 0.0f, 1.0f, 0.0f, 0.0 }; + XMStoreFloat4x4(&m_viewMatrix, XMMatrixLookAtLH(c_eye, c_at, c_up)); + + // Initialize the lighting parameters + m_lightDirs[0] = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); + m_lightDirs[1] = XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f); + + m_lightColors[0] = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); + m_lightColors[1] = XMFLOAT4(0.5f, 0.0f, 0.0f, 1.0f); + + // Initialize the scene output color + m_outputColor = XMFLOAT4(0, 0, 0, 0); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + // Initialize the projection matrix + auto size = m_deviceResources->GetOutputSize(); + XMMATRIX projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, float(size.right) / float(size.bottom), 0.01f, 100.0f); + + XMFLOAT4X4 orient = m_deviceResources->GetOrientationTransform3D(); + + XMStoreFloat4x4(&m_projectionMatrix, projection * XMLoadFloat4x4(&orient)); + + // The frame index will be reset to zero when the window size changes + // So we need to tell the GPU to signal our fence starting with zero + uint64_t currentIdx = m_deviceResources->GetCurrentFrameIndex(); + m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), currentIdx); +} + +void Sample::OnDeviceLost() +{ + m_rootSignature.Reset(); + m_lambertPipelineState.Reset(); + m_solidColorPipelineState.Reset(); + m_fence.Reset(); + m_vertexBuffer.Reset(); + m_indexBuffer.Reset(); + m_mappedConstantData = nullptr; + m_constantDataGpuAddr = 0; + m_perFrameConstants.Reset(); +} +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.h b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.h new file mode 100644 index 00000000..cefe4105 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.h @@ -0,0 +1,127 @@ +//-------------------------------------------------------------------------------------- +// SimpleLightingUWP12.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "DeviceResources.h" +#include "StepTimer.h" + + +// A basic sample implementation that creates a D3D12 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + +private: + + struct ConstantBuffer + { + DirectX::XMMATRIX worldMatrix; + DirectX::XMMATRIX viewMatrix; + DirectX::XMMATRIX projectionMatrix; + DirectX::XMVECTOR lightDir[2]; + DirectX::XMVECTOR lightColor[2]; + DirectX::XMVECTOR outputColor; + }; + + // We'll allocate space for several of these and they will need to be padded for alignment. + static_assert(sizeof(ConstantBuffer) == 272, "Checking the size here."); + + // D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT < 272 < 2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT + // Create a union with the correct size and enough room for one ConstantBuffer + union PaddedConstantBuffer + { + ConstantBuffer constants; + uint8_t bytes[2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT]; + }; + + // Check the exact size of the PaddedConstantBuffer to make sure it will align properly + static_assert(sizeof(PaddedConstantBuffer) == 2 * D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, "PaddedConstantBuffer is not aligned properly"); + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + + // DirectXTK objects. + Microsoft::WRL::ComPtr m_rootSignature; + Microsoft::WRL::ComPtr m_lambertPipelineState; + Microsoft::WRL::ComPtr m_solidColorPipelineState; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_perFrameConstants; + PaddedConstantBuffer* m_mappedConstantData; + D3D12_GPU_VIRTUAL_ADDRESS m_constantDataGpuAddr; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView; + D3D12_INDEX_BUFFER_VIEW m_indexBufferView; + + // In this simple sample, we know that there are three draw calls + // and we will update the scene constants for each draw call. + static const unsigned int c_numDrawCalls = 3; + + // A synchronization fence and an event. These members will be used + // to synchronize the CPU with the GPU so that there will be no + // contention for the constant buffers. + Microsoft::WRL::ComPtr m_fence; + Microsoft::WRL::Wrappers::Event m_fenceEvent; + + // Index in the root parameter table + static const UINT c_rootParameterCB = 0; + + // Scene constants, updated per-frame + float m_curRotationAngleRad; + + // These computed values will be loaded into a ConstantBuffer + // during Render + DirectX::XMFLOAT4X4 m_worldMatrix; + DirectX::XMFLOAT4X4 m_viewMatrix; + DirectX::XMFLOAT4X4 m_projectionMatrix; + DirectX::XMFLOAT4 m_lightDirs[2]; + DirectX::XMFLOAT4 m_lightColors[2]; + DirectX::XMFLOAT4 m_outputColor; +}; \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.sln b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.sln new file mode 100644 index 00000000..5b7fee85 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleLightingUWP12", "SimpleLightingUWP12.vcxproj", "{2D643F62-B746-49A0-903B-ED6C826A9F52}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|ARM.ActiveCfg = Debug|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|ARM.Build.0 = Debug|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|ARM.Deploy.0 = Debug|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x64.ActiveCfg = Debug|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x64.Build.0 = Debug|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x64.Deploy.0 = Debug|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x86.ActiveCfg = Debug|Win32 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x86.Build.0 = Debug|Win32 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Debug|x86.Deploy.0 = Debug|Win32 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|ARM.ActiveCfg = Release|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|ARM.Build.0 = Release|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|ARM.Deploy.0 = Release|ARM + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x64.ActiveCfg = Release|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x64.Build.0 = Release|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x64.Deploy.0 = Release|x64 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x86.ActiveCfg = Release|Win32 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x86.Build.0 = Release|Win32 + {2D643F62-B746-49A0-903B-ED6C826A9F52}.Release|x86.Deploy.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj new file mode 100644 index 00000000..aad25d60 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj @@ -0,0 +1,306 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {2d643f62-b746-49a0-903b-ed6c826a9f52} + DirectXApp + SimpleLightingUWP12 + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + true + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + SimpleLightingUWP12_TemporaryKey.pfx + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + d2d1.lib; d3d12.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 5.1 + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + + + + + + + + + + + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + + + + Pixel + Pixel + Pixel + Pixel + Pixel + Pixel + LambertPS + LambertPS + LambertPS + LambertPS + LambertPS + LambertPS + + + Pixel + Pixel + Pixel + Pixel + Pixel + Pixel + SolidColorPS + SolidColorPS + SolidColorPS + SolidColorPS + SolidColorPS + SolidColorPS + + + Vertex + Vertex + Vertex + Vertex + Vertex + Vertex + TriangleVS + TriangleVS + TriangleVS + TriangleVS + TriangleVS + TriangleVS + + + + + + + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj.filters b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj.filters new file mode 100644 index 00000000..9959ab75 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12.vcxproj.filters @@ -0,0 +1,83 @@ + + + + + 1fda9b28-2a50-4995-acfc-8bccdb53230d + + + d66fe45c-ff66-4e9d-8e30-28244a830931 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {aa473492-121f-4e4e-ad9a-65846906512b} + + + {efe88b02-f065-480d-97c4-5c17f574d168} + + + + + + + Common + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + shaders + + + + + + shaders + + + shaders + + + shaders + + + \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12_TemporaryKey.pfx b/Samples/IntroGraphics/SimpleLightingUWP12/SimpleLightingUWP12_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..ae581c65e146d2bbd122ee9673534f539bc03bea GIT binary patch literal 2456 zcmXqL;_P8!WHxBx^kC!EYV&CO&dbQoxS)yClBJ2$)S!ve(4dL+6N(h;W0oe?`vy&{ zw+)(Dud{JOb@6a9GA(Fg`DW0>^2tDkjSD8s$ZWvJ!oh!|QpAX#$(M;Xv$uBR4>f9d)EanrB9 ztD8=T&h+~lGQ)4;cDe9?$is_Qai!S54Y>aP-tn7r+=aJXy|*^7;;-$tClj{v>GJ>n zEZ~2Mh2!9bw{zy6a`hVRtZkh2gXzx$zD2>)G@EqH;)SfT-YLzH zj$6#0yJDS5z|z;wS6A+k_l-C>N4JLWdbH-(b?YBL$eQVy`Jidiqnwxz%nHADv$OT; z7_h99-dl0_+Y%v_;(Rrer;X8@FZGA`?75Y6m1*mKuZGR9d)!Subxf{L_&HD1&u;en zcVG8@;LG~h^yE{)jgRkDlIrZ{6mR2Rx+0|D-5K%1{&}lno2|Vh>hIWz@9yGGoT^Z= z>1u+*r({3Dr^Vm=J9;iVs89O3k6G)tFZ&CT_FX-RXB`(XzA0tco3uPAjL-Zw>-`fg z(^wB&U)89)`s3T1&xLd1(&vfzoS6KM)y6eKyV{eh^Rm^pYez3WE0MBMPW|hy^hfna1IhQI$uKw_{>x7i5xzf@D;j9(yE@k48=QlrU)nzW0V=cAY>z=x7 z+b!0f8jFvmF-qCfJqixmONT#o)tI)rQ<6pJ`Tyz6pS|lMek|OZxLb0`W$n(Bt}@mi zb?&S7Zgp1KZ+SfS(&>qFwofe%PxaC$6_hNUsiW#tUdNn;d-A{ z@Udc+<8?M`wk_Lb0k%)a-9;uP)4^NvMo zZ4_gl-!k!8P>uJ#2#C3 zh}NA}*yz6~*m?dpu~v~en_7kUo&R^@>2=}st6%^AW=QV49QF9D%&p+PY8`8w+0t+8 z9%!w1%DyMVB9^nm-q)LL!w0WeAo_&0%*?#`;p^M6IZ_w@}2YU^drN>%MT;ib?5K4eX@Fn!e!RFgo}r zU&@|-#BI0qNuEW_(Or#sqBh;NcP>77cj!>&^S3*;OnzS%8&iL#Tz5K;-CfhihK*+p zgyF>`r>G$t3kxFy1A{?0LQureOU{GAl);q2lEDB>rZJc^=rUL`Br&8im@?=xm@pVK zSTdx7#Vi;S87vue84MW=7}6Ll8Il@yg@v&czF1$25tfJ=7kj*vg`OCKf;r}JdL;9Yy zFHXCf$`tqA(R<T zp%1n#xMlL?^_DLkzt~G#_~-N}w(?j%p0&2ZrkmaK zR*$g9!wkP4<w`hERy_jvb{!XF=`{iUxly;O~{W}EM$AfEj0&hoOynsveElau08j|iX2AKRVuz9s7OI2-Ry7N|35VmW=sNF*XPzVzV){eX(k zmzF*^+Tp3eaLv2 +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/TriangleVS.hlsl b/Samples/IntroGraphics/SimpleLightingUWP12/TriangleVS.hlsl new file mode 100644 index 00000000..1d13961b --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/TriangleVS.hlsl @@ -0,0 +1,2 @@ +// TriangleVS.hlsl file to provide an MSBuild target for the TriangleVS vertex-shader entry point +#include "SimpleLighting.hlsli" \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/d3dx12.h b/Samples/IntroGraphics/SimpleLightingUWP12/d3dx12.h new file mode 100644 index 00000000..351914d3 --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/d3dx12.h @@ -0,0 +1,1534 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#ifndef __D3DX12_H__ +#define __D3DX12_H__ + +#include "d3d12.h" + +#if defined( __cplusplus ) + +struct CD3DX12_DEFAULT {}; +extern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT; + +//------------------------------------------------------------------------------------------------ +inline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ + return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width && + l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth; +} + +//------------------------------------------------------------------------------------------------ +inline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RECT : public D3D12_RECT +{ + CD3DX12_RECT() + {} + explicit CD3DX12_RECT( const D3D12_RECT& o ) : + D3D12_RECT( o ) + {} + explicit CD3DX12_RECT( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + right = Right; + bottom = Bottom; + } + ~CD3DX12_RECT() {} + operator const D3D12_RECT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BOX : public D3D12_BOX +{ + CD3DX12_BOX() + {} + explicit CD3DX12_BOX( const D3D12_BOX& o ) : + D3D12_BOX( o ) + {} + explicit CD3DX12_BOX( + LONG Left, + LONG Right ) + { + left = Left; + top = 0; + front = 0; + right = Right; + bottom = 1; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Right, + LONG Bottom ) + { + left = Left; + top = Top; + front = 0; + right = Right; + bottom = Bottom; + back = 1; + } + explicit CD3DX12_BOX( + LONG Left, + LONG Top, + LONG Front, + LONG Right, + LONG Bottom, + LONG Back ) + { + left = Left; + top = Top; + front = Front; + right = Right; + bottom = Bottom; + back = Back; + } + ~CD3DX12_BOX() {} + operator const D3D12_BOX&() const { return *this; } +}; +inline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r ) +{ + return l.left == r.left && l.top == r.top && l.front == r.front && + l.right == r.right && l.bottom == r.bottom && l.back == r.back; +} +inline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC +{ + CD3DX12_DEPTH_STENCIL_DESC() + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) : + D3D12_DEPTH_STENCIL_DESC( o ) + {} + explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) + { + DepthEnable = TRUE; + DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + DepthFunc = D3D12_COMPARISON_FUNC_LESS; + StencilEnable = FALSE; + StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = + { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS }; + FrontFace = defaultStencilOp; + BackFace = defaultStencilOp; + } + explicit CD3DX12_DEPTH_STENCIL_DESC( + BOOL depthEnable, + D3D12_DEPTH_WRITE_MASK depthWriteMask, + D3D12_COMPARISON_FUNC depthFunc, + BOOL stencilEnable, + UINT8 stencilReadMask, + UINT8 stencilWriteMask, + D3D12_STENCIL_OP frontStencilFailOp, + D3D12_STENCIL_OP frontStencilDepthFailOp, + D3D12_STENCIL_OP frontStencilPassOp, + D3D12_COMPARISON_FUNC frontStencilFunc, + D3D12_STENCIL_OP backStencilFailOp, + D3D12_STENCIL_OP backStencilDepthFailOp, + D3D12_STENCIL_OP backStencilPassOp, + D3D12_COMPARISON_FUNC backStencilFunc ) + { + DepthEnable = depthEnable; + DepthWriteMask = depthWriteMask; + DepthFunc = depthFunc; + StencilEnable = stencilEnable; + StencilReadMask = stencilReadMask; + StencilWriteMask = stencilWriteMask; + FrontFace.StencilFailOp = frontStencilFailOp; + FrontFace.StencilDepthFailOp = frontStencilDepthFailOp; + FrontFace.StencilPassOp = frontStencilPassOp; + FrontFace.StencilFunc = frontStencilFunc; + BackFace.StencilFailOp = backStencilFailOp; + BackFace.StencilDepthFailOp = backStencilDepthFailOp; + BackFace.StencilPassOp = backStencilPassOp; + BackFace.StencilFunc = backStencilFunc; + } + ~CD3DX12_DEPTH_STENCIL_DESC() {} + operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC +{ + CD3DX12_BLEND_DESC() + {} + explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) : + D3D12_BLEND_DESC( o ) + {} + explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) + { + AlphaToCoverageEnable = FALSE; + IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + RenderTarget[ i ] = defaultRenderTargetBlendDesc; + } + ~CD3DX12_BLEND_DESC() {} + operator const D3D12_BLEND_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC +{ + CD3DX12_RASTERIZER_DESC() + {} + explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) : + D3D12_RASTERIZER_DESC( o ) + {} + explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + MultisampleEnable = FALSE; + AntialiasedLineEnable = FALSE; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + INT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + BOOL multisampleEnable, + BOOL antialiasedLineEnable, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + MultisampleEnable = multisampleEnable; + AntialiasedLineEnable = antialiasedLineEnable; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + ~CD3DX12_RASTERIZER_DESC() {} + operator const D3D12_RASTERIZER_DESC&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO +{ + CD3DX12_RESOURCE_ALLOCATION_INFO() + {} + explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) : + D3D12_RESOURCE_ALLOCATION_INFO( o ) + {} + CD3DX12_RESOURCE_ALLOCATION_INFO( + UINT64 size, + UINT64 alignment ) + { + SizeInBytes = size; + Alignment = alignment; + } + operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES +{ + CD3DX12_HEAP_PROPERTIES() + {} + explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) : + D3D12_HEAP_PROPERTIES(o) + {} + CD3DX12_HEAP_PROPERTIES( + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = D3D12_HEAP_TYPE_CUSTOM; + CPUPageProperty = cpuPageProperty; + MemoryPoolPreference = memoryPoolPreference; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + explicit CD3DX12_HEAP_PROPERTIES( + D3D12_HEAP_TYPE type, + UINT creationNodeMask = 1, + UINT nodeMask = 1 ) + { + Type = type; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = creationNodeMask; + VisibleNodeMask = nodeMask; + } + operator const D3D12_HEAP_PROPERTIES&() const { return *this; } + bool IsCPUAccessible() const + { + return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM && + (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); + } +}; +inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ + return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && + l.MemoryPoolPreference == r.MemoryPoolPreference && + l.CreationNodeMask == r.CreationNodeMask && + l.VisibleNodeMask == r.VisibleNodeMask; +} +inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC +{ + CD3DX12_HEAP_DESC() + {} + explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) : + D3D12_HEAP_DESC(o) + {} + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_PROPERTIES properties, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = properties; + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_HEAP_TYPE type, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + UINT64 size, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + UINT64 alignment = 0, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = size; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_PROPERTIES properties, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = properties; + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_HEAP_TYPE type, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( type ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + CD3DX12_HEAP_DESC( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_CPU_PAGE_PROPERTY cpuPageProperty, + D3D12_MEMORY_POOL memoryPoolPreference, + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ) + { + SizeInBytes = resAllocInfo.SizeInBytes; + Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference ); + Alignment = resAllocInfo.Alignment; + Flags = flags; + } + operator const D3D12_HEAP_DESC&() const { return *this; } + bool IsCPUAccessible() const + { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); } +}; +inline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ + return l.SizeInBytes == r.SizeInBytes && + l.Properties == r.Properties && + l.Alignment == r.Alignment && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE +{ + CD3DX12_CLEAR_VALUE() + {} + explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) : + D3D12_CLEAR_VALUE(o) + {} + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + const FLOAT color[4] ) + { + Format = format; + memcpy( Color, color, sizeof( Color ) ); + } + CD3DX12_CLEAR_VALUE( + DXGI_FORMAT format, + FLOAT depth, + UINT8 stencil ) + { + Format = format; + /* Use memcpy to preserve NAN values */ + memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) ); + DepthStencil.Stencil = stencil; + } + operator const D3D12_CLEAR_VALUE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RANGE : public D3D12_RANGE +{ + CD3DX12_RANGE() + {} + explicit CD3DX12_RANGE(const D3D12_RANGE &o) : + D3D12_RANGE(o) + {} + CD3DX12_RANGE( + SIZE_T begin, + SIZE_T end ) + { + Begin = begin; + End = end; + } + operator const D3D12_RANGE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE +{ + CD3DX12_SHADER_BYTECODE() + {} + explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) : + D3D12_SHADER_BYTECODE(o) + {} + CD3DX12_SHADER_BYTECODE( + ID3DBlob* pShaderBlob ) + { + pShaderBytecode = pShaderBlob->GetBufferPointer(); + BytecodeLength = pShaderBlob->GetBufferSize(); + } + CD3DX12_SHADER_BYTECODE( + void* _pShaderBytecode, + SIZE_T bytecodeLength ) + { + pShaderBytecode = _pShaderBytecode; + BytecodeLength = bytecodeLength; + } + operator const D3D12_SHADER_BYTECODE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE +{ + CD3DX12_TILED_RESOURCE_COORDINATE() + {} + explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) : + D3D12_TILED_RESOURCE_COORDINATE(o) + {} + CD3DX12_TILED_RESOURCE_COORDINATE( + UINT x, + UINT y, + UINT z, + UINT subresource ) + { + X = x; + Y = y; + Z = z; + Subresource = subresource; + } + operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE +{ + CD3DX12_TILE_REGION_SIZE() + {} + explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) : + D3D12_TILE_REGION_SIZE(o) + {} + CD3DX12_TILE_REGION_SIZE( + UINT numTiles, + BOOL useBox, + UINT width, + UINT16 height, + UINT16 depth ) + { + NumTiles = numTiles; + UseBox = useBox; + Width = width; + Height = height; + Depth = depth; + } + operator const D3D12_TILE_REGION_SIZE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING +{ + CD3DX12_SUBRESOURCE_TILING() + {} + explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) : + D3D12_SUBRESOURCE_TILING(o) + {} + CD3DX12_SUBRESOURCE_TILING( + UINT widthInTiles, + UINT16 heightInTiles, + UINT16 depthInTiles, + UINT startTileIndexInOverallResource ) + { + WidthInTiles = widthInTiles; + HeightInTiles = heightInTiles; + DepthInTiles = depthInTiles; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_SUBRESOURCE_TILING&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE +{ + CD3DX12_TILE_SHAPE() + {} + explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) : + D3D12_TILE_SHAPE(o) + {} + CD3DX12_TILE_SHAPE( + UINT widthInTexels, + UINT heightInTexels, + UINT depthInTexels ) + { + WidthInTexels = widthInTexels; + HeightInTexels = heightInTexels; + DepthInTexels = depthInTexels; + } + operator const D3D12_TILE_SHAPE&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER +{ + CD3DX12_RESOURCE_BARRIER() + {} + explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) : + D3D12_RESOURCE_BARRIER(o) + {} + static inline CD3DX12_RESOURCE_BARRIER Transition( + _In_ ID3D12Resource* pResource, + D3D12_RESOURCE_STATES stateBefore, + D3D12_RESOURCE_STATES stateAfter, + UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, + D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + result.Flags = flags; + barrier.Transition.pResource = pResource; + barrier.Transition.StateBefore = stateBefore; + barrier.Transition.StateAfter = stateAfter; + barrier.Transition.Subresource = subresource; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER Aliasing( + _In_ ID3D12Resource* pResourceBefore, + _In_ ID3D12Resource* pResourceAfter) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; + barrier.Aliasing.pResourceBefore = pResourceBefore; + barrier.Aliasing.pResourceAfter = pResourceAfter; + return result; + } + static inline CD3DX12_RESOURCE_BARRIER UAV( + _In_ ID3D12Resource* pResource) + { + CD3DX12_RESOURCE_BARRIER result; + ZeroMemory(&result, sizeof(result)); + D3D12_RESOURCE_BARRIER &barrier = result; + result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = pResource; + return result; + } + operator const D3D12_RESOURCE_BARRIER&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO +{ + CD3DX12_PACKED_MIP_INFO() + {} + explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) : + D3D12_PACKED_MIP_INFO(o) + {} + CD3DX12_PACKED_MIP_INFO( + UINT8 numStandardMips, + UINT8 numPackedMips, + UINT numTilesForPackedMips, + UINT startTileIndexInOverallResource ) + { + NumStandardMips = numStandardMips; + NumPackedMips = numPackedMips; + NumTilesForPackedMips = numTilesForPackedMips; + StartTileIndexInOverallResource = startTileIndexInOverallResource; + } + operator const D3D12_PACKED_MIP_INFO&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT +{ + CD3DX12_SUBRESOURCE_FOOTPRINT() + {} + explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) : + D3D12_SUBRESOURCE_FOOTPRINT(o) + {} + CD3DX12_SUBRESOURCE_FOOTPRINT( + DXGI_FORMAT format, + UINT width, + UINT height, + UINT depth, + UINT rowPitch ) + { + Format = format; + Width = width; + Height = height; + Depth = depth; + RowPitch = rowPitch; + } + explicit CD3DX12_SUBRESOURCE_FOOTPRINT( + const D3D12_RESOURCE_DESC& resDesc, + UINT rowPitch ) + { + Format = resDesc.Format; + Width = UINT( resDesc.Width ); + Height = resDesc.Height; + Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1); + RowPitch = rowPitch; + } + operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION +{ + CD3DX12_TEXTURE_COPY_LOCATION() + {} + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub) + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + SubresourceIndex = Sub; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE +{ + CD3DX12_DESCRIPTOR_RANGE() { } + explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) : + D3D12_DESCRIPTOR_RANGE(o) + {} + CD3DX12_DESCRIPTOR_RANGE( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + inline void Init( + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart); + } + + static inline void Init( + _Out_ D3D12_DESCRIPTOR_RANGE &range, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT numDescriptors, + UINT baseShaderRegister, + UINT registerSpace = 0, + UINT offsetInDescriptorsFromTableStart = + D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + range.RangeType = rangeType; + range.NumDescriptors = numDescriptors; + range.BaseShaderRegister = baseShaderRegister; + range.RegisterSpace = registerSpace; + range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE +{ + CD3DX12_ROOT_DESCRIPTOR_TABLE() {} + explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) : + D3D12_ROOT_DESCRIPTOR_TABLE(o) + {} + CD3DX12_ROOT_DESCRIPTOR_TABLE( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(numDescriptorRanges, _pDescriptorRanges); + } + + inline void Init( + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + Init(*this, numDescriptorRanges, _pDescriptorRanges); + } + + static inline void Init( + _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable, + UINT numDescriptorRanges, + _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges) + { + rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges; + rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS +{ + CD3DX12_ROOT_CONSTANTS() {} + explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) : + D3D12_ROOT_CONSTANTS(o) + {} + CD3DX12_ROOT_CONSTANTS( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(num32BitValues, shaderRegister, registerSpace); + } + + inline void Init( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, num32BitValues, shaderRegister, registerSpace); + } + + static inline void Init( + _Out_ D3D12_ROOT_CONSTANTS &rootConstants, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0) + { + rootConstants.Num32BitValues = num32BitValues; + rootConstants.ShaderRegister = shaderRegister; + rootConstants.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR +{ + CD3DX12_ROOT_DESCRIPTOR() {} + explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) : + D3D12_ROOT_DESCRIPTOR(o) + {} + CD3DX12_ROOT_DESCRIPTOR( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(shaderRegister, registerSpace); + } + + inline void Init( + UINT shaderRegister, + UINT registerSpace = 0) + { + Init(*this, shaderRegister, registerSpace); + } + + static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0) + { + table.ShaderRegister = shaderRegister; + table.RegisterSpace = registerSpace; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER +{ + CD3DX12_ROOT_PARAMETER() {} + explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) : + D3D12_ROOT_PARAMETER(o) + {} + + static inline void InitAsDescriptorTable( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges); + } + + static inline void InitAsConstants( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace); + } + + static inline void InitAsConstantBufferView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsShaderResourceView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + static inline void InitAsUnorderedAccessView( + _Out_ D3D12_ROOT_PARAMETER &rootParam, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; + rootParam.ShaderVisibility = visibility; + CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace); + } + + inline void InitAsDescriptorTable( + UINT numDescriptorRanges, + _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility); + } + + inline void InitAsConstants( + UINT num32BitValues, + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility); + } + + inline void InitAsConstantBufferView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsShaderResourceView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility); + } + + inline void InitAsUnorderedAccessView( + UINT shaderRegister, + UINT registerSpace = 0, + D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL) + { + InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility); + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC +{ + CD3DX12_STATIC_SAMPLER_DESC() {} + explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) : + D3D12_STATIC_SAMPLER_DESC(o) + {} + CD3DX12_STATIC_SAMPLER_DESC( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0) + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace); + } + +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC +{ + CD3DX12_ROOT_SIGNATURE_DESC() {} + explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) : + D3D12_ROOT_SIGNATURE_DESC(o) + {} + CD3DX12_ROOT_SIGNATURE_DESC( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT) + { + Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE); + } + + inline void Init( + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags); + } + + static inline void Init( + _Out_ D3D12_ROOT_SIGNATURE_DESC &desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) + { + desc.NumParameters = numParameters; + desc.pParameters = _pParameters; + desc.NumStaticSamplers = numStaticSamplers; + desc.pStaticSamplers = _pStaticSamplers; + desc.Flags = flags; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) : + D3D12_CPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE +{ + CD3DX12_GPU_DESCRIPTOR_HANDLE() {} + explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) : + D3D12_GPU_DESCRIPTOR_HANDLE(o) + {} + CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize) + { + InitOffsetted(other, offsetScaledByIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize) + { + ptr += offsetInDescriptors * descriptorIncrementSize; + return *this; + } + CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) + { + ptr += offsetScaledByIncrementSize; + return *this; + } + inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr == other.ptr); + } + inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) + { + return (ptr != other.ptr); + } + CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other) + { + ptr = other.ptr; + return *this; + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + InitOffsetted(*this, base, offsetScaledByIncrementSize); + } + + inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize); + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize) + { + handle.ptr = base.ptr + offsetScaledByIncrementSize; + } + + static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize) + { + handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize; + } +}; + +//------------------------------------------------------------------------------------------------ +inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) +{ + return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; +} + +//------------------------------------------------------------------------------------------------ +template +inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) +{ + MipSlice = static_cast(Subresource % MipLevels); + ArraySlice = static_cast((Subresource / MipLevels) % ArraySize); + PlaneSlice = static_cast(Subresource / (MipLevels * ArraySize)); +} + +//------------------------------------------------------------------------------------------------ +inline UINT8 D3D12GetFormatPlaneCount( + _In_ ID3D12Device* pDevice, + DXGI_FORMAT Format + ) +{ + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format}; + if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)))) + { + return 0; + } + return formatInfo.PlaneCount; +} + +//------------------------------------------------------------------------------------------------ +struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC +{ + CD3DX12_RESOURCE_DESC() + {} + explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) : + D3D12_RESOURCE_DESC( o ) + {} + CD3DX12_RESOURCE_DESC( + D3D12_RESOURCE_DIMENSION dimension, + UINT64 alignment, + UINT64 width, + UINT height, + UINT16 depthOrArraySize, + UINT16 mipLevels, + DXGI_FORMAT format, + UINT sampleCount, + UINT sampleQuality, + D3D12_TEXTURE_LAYOUT layout, + D3D12_RESOURCE_FLAGS flags ) + { + Dimension = dimension; + Alignment = alignment; + Width = width; + Height = height; + DepthOrArraySize = depthOrArraySize; + MipLevels = mipLevels; + Format = format; + SampleDesc.Count = sampleCount; + SampleDesc.Quality = sampleQuality; + Layout = layout; + Flags = flags; + } + static inline CD3DX12_RESOURCE_DESC Buffer( + const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, + 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Buffer( + UINT64 width, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, + DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex1D( + DXGI_FORMAT format, + UINT64 width, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, + mipLevels, format, 1, 0, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex2D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 arraySize = 1, + UINT16 mipLevels = 0, + UINT sampleCount = 1, + UINT sampleQuality = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, + mipLevels, format, sampleCount, sampleQuality, layout, flags ); + } + static inline CD3DX12_RESOURCE_DESC Tex3D( + DXGI_FORMAT format, + UINT64 width, + UINT height, + UINT16 depth, + UINT16 mipLevels = 0, + D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE, + D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + UINT64 alignment = 0 ) + { + return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, + mipLevels, format, 1, 0, layout, flags ); + } + inline UINT16 Depth() const + { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT16 ArraySize() const + { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); } + inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const + { return D3D12GetFormatPlaneCount(pDevice, Format); } + inline UINT Subresources(_In_ ID3D12Device* pDevice) const + { return MipLevels * ArraySize() * PlaneCount(pDevice); } + inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) + { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); } + operator const D3D12_RESOURCE_DESC&() const { return *this; } +}; +inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ + return l.Dimension == r.Dimension && + l.Alignment == r.Alignment && + l.Width == r.Width && + l.Height == r.Height && + l.DepthOrArraySize == r.DepthOrArraySize && + l.MipLevels == r.MipLevels && + l.Format == r.Format && + l.SampleDesc.Count == r.SampleDesc.Count && + l.SampleDesc.Quality == r.SampleDesc.Quality && + l.Layout == r.Layout && + l.Flags == r.Flags; +} +inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) +{ return !( l == r ); } + +//------------------------------------------------------------------------------------------------ +// Row-by-row memcpy +inline void MemcpySubresource( + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) +{ + for (UINT z = 0; z < NumSlices; ++z) + { + BYTE* pDestSlice = reinterpret_cast(pDest->pData) + pDest->SlicePitch * z; + const BYTE* pSrcSlice = reinterpret_cast(pSrc->pData) + pSrc->SlicePitch * z; + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * y, + RowSizeInBytes); + } + } +} + +//------------------------------------------------------------------------------------------------ +// Returns required size of a buffer to be used for data upload +inline UINT64 GetRequiredIntermediateSize( + _In_ ID3D12Resource* pDestinationResource, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) +{ + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + UINT64 RequiredSize = 0; + + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize); + pDevice->Release(); + + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// All arrays must be populated (e.g. by calling GetCopyableFootprints) +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) +{ + // Minor validation + D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(); + D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > (SIZE_T)-1 || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] }; + MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, NULL); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) ); + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; +} + +//------------------------------------------------------------------------------------------------ +// Heap-allocating UpdateSubresources implementation +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + UINT64 MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == NULL) + { + return 0; + } + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast(pMem); + UINT64* pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + pDevice->Release(); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; +} + +//------------------------------------------------------------------------------------------------ +// Stack-allocating UpdateSubresources implementation +template +inline UINT64 UpdateSubresources( + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0, MaxSubresources) UINT FirstSubresource, + _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData) +{ + UINT64 RequiredSize = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources]; + UINT NumRows[MaxSubresources]; + UINT64 RowSizesInBytes[MaxSubresources]; + + D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + ID3D12Device* pDevice; + pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); + pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize); + pDevice->Release(); + + return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData); +} + +//------------------------------------------------------------------------------------------------ +inline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) +{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; } + +//------------------------------------------------------------------------------------------------ +inline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp) +{ + // This cast is useful for passing strongly typed command list pointers into + // ExecuteCommandLists. + // This cast is valid as long as the const-ness is respected. D3D12 APIs do + // respect the const-ness of their arguments. + return reinterpret_cast(pp); +} + + +#endif // defined( __cplusplus ) + +#endif //__D3DX12_H__ + + + diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/pch.cpp b/Samples/IntroGraphics/SimpleLightingUWP12/pch.cpp new file mode 100644 index 00000000..851c81be --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/IntroGraphics/SimpleLightingUWP12/pch.h b/Samples/IntroGraphics/SimpleLightingUWP12/pch.h new file mode 100644 index 00000000..81c31dde --- /dev/null +++ b/Samples/IntroGraphics/SimpleLightingUWP12/pch.h @@ -0,0 +1,68 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#include +#include +#include +#include + +#include "d3dx12.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "GamePad.h" +#include "GraphicsMemory.h" +#include "Keyboard.h" +#include "Mouse.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj index 92a15bee..11af48d2 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj +++ b/Samples/IntroGraphics/SimpleTextureUWP/SimpleTextureUWP.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp index c7109625..a7415aba 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP12/DeviceResources.cpp @@ -217,6 +217,10 @@ void DX::DeviceResources::CreateDeviceResources() m_fenceValues[m_backBufferIndex]++; m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } } // These resources need to be recreated every time the window size is changed. diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp index b49e7b38..c671cf1a 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.cpp @@ -170,6 +170,7 @@ void Sample::Render() // Show the new frame. PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"Present"); m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); PIXEndEvent(m_deviceResources->GetCommandQueue()); } @@ -246,6 +247,8 @@ void Sample::CreateDeviceDependentResources() { auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device); + // Create descriptor heaps. { // Describe and create a shader resource view (SRV) heap for the texture. @@ -475,6 +478,7 @@ void Sample::OnDeviceLost() m_pipelineState.Reset(); m_rootSignature.Reset(); m_srvHeap.Reset(); + m_graphicsMemory.reset(); } void Sample::OnDeviceRestored() diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.h b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.h index 455960ca..0ab74e4f 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.h +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.h @@ -61,6 +61,9 @@ private: std::unique_ptr m_gamePad; std::unique_ptr m_keyboard; + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + // Direct3D 12 objects Microsoft::WRL::ComPtr m_srvHeap; Microsoft::WRL::ComPtr m_rootSignature; diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.sln b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.sln index 22134bb6..c8308168 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.sln +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.sln @@ -1,11 +1,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTextureUWP12", "SimpleTextureUWP12.vcxproj", "{3F23A13A-F9BF-4A86-B0FA-F5F0A93CB452}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK", "..\..\..\Kits\DirectXTK\DirectXTK_Windows10.vcxproj", "{F4776924-619C-42C7-88B2-82C947CCC9E7}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,18 +35,18 @@ Global {3F23A13A-F9BF-4A86-B0FA-F5F0A93CB452}.Release|x86.ActiveCfg = Release|Win32 {3F23A13A-F9BF-4A86-B0FA-F5F0A93CB452}.Release|x86.Build.0 = Release|Win32 {3F23A13A-F9BF-4A86-B0FA-F5F0A93CB452}.Release|x86.Deploy.0 = Release|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.ActiveCfg = Debug|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.Build.0 = Debug|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.ActiveCfg = Debug|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.Build.0 = Debug|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.ActiveCfg = Debug|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.Build.0 = Debug|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.ActiveCfg = Release|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.Build.0 = Release|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.ActiveCfg = Release|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.Build.0 = Release|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.ActiveCfg = Release|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.Build.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj index c4dcdd44..e8a098dc 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj +++ b/Samples/IntroGraphics/SimpleTextureUWP12/SimpleTextureUWP12.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true @@ -109,7 +108,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -127,7 +126,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -145,7 +144,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -164,7 +163,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -183,7 +182,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -201,7 +200,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -248,11 +247,6 @@ - - - {f4776924-619c-42c7-88b2-82c947ccc9e7} - - Pixel @@ -271,6 +265,11 @@ Vertex + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + diff --git a/Samples/IntroGraphics/SimpleTextureUWP12/pch.h b/Samples/IntroGraphics/SimpleTextureUWP12/pch.h index 887dcf72..d4a67146 100644 --- a/Samples/IntroGraphics/SimpleTextureUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleTextureUWP12/pch.h @@ -36,6 +36,7 @@ #endif #include "GamePad.h" +#include "GraphicsMemory.h" #include "Keyboard.h" #include "Mouse.h" diff --git a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj index c627a194..910d7427 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj +++ b/Samples/IntroGraphics/SimpleTriangleUWP/SimpleTriangleUWP.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp index c7109625..a7415aba 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/DeviceResources.cpp @@ -217,6 +217,10 @@ void DX::DeviceResources::CreateDeviceResources() m_fenceValues[m_backBufferIndex]++; m_fenceEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + if (!m_fenceEvent.IsValid()) + { + throw std::exception("CreateEvent"); + } } // These resources need to be recreated every time the window size is changed. diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp index 42f77470..9a2a7cbf 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.cpp @@ -124,6 +124,7 @@ void Sample::Render() // Show the new frame. PIXBeginEvent(m_deviceResources->GetCommandQueue(), PIX_COLOR_DEFAULT, L"Present"); m_deviceResources->Present(); + m_graphicsMemory->Commit(m_deviceResources->GetCommandQueue()); PIXEndEvent(m_deviceResources->GetCommandQueue()); } @@ -200,6 +201,8 @@ void Sample::CreateDeviceDependentResources() { auto device = m_deviceResources->GetD3DDevice(); + m_graphicsMemory = std::make_unique(device); + // Create an empty root signature. { CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; @@ -293,6 +296,7 @@ void Sample::OnDeviceLost() m_vertexBuffer.Reset(); m_pipelineState.Reset(); m_rootSignature.Reset(); + m_graphicsMemory.reset(); } void Sample::OnDeviceRestored() diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.h b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.h index d9a27ea3..186848f7 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.h @@ -62,6 +62,9 @@ private: std::unique_ptr m_keyboard; std::unique_ptr m_mouse; + // DirectXTK objects. + std::unique_ptr m_graphicsMemory; + // Direct3D 12 objects Microsoft::WRL::ComPtr m_rootSignature; Microsoft::WRL::ComPtr m_pipelineState; diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.sln b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.sln index 8d8a4794..84f6dd32 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.sln +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.sln @@ -1,11 +1,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTriangleUWP12", "SimpleTriangleUWP12.vcxproj", "{930ECC6F-E823-4989-9FAE-524452C6BF66}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK", "..\..\..\Kits\DirectXTK\DirectXTK_Windows10.vcxproj", "{F4776924-619C-42C7-88B2-82C947CCC9E7}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK12", "..\..\..\Kits\DirectXTK12\DirectXTK_Windows10.vcxproj", "{945B8F0E-AE5F-447C-933A-9D069532D3E4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,18 +35,18 @@ Global {930ECC6F-E823-4989-9FAE-524452C6BF66}.Release|x86.ActiveCfg = Release|Win32 {930ECC6F-E823-4989-9FAE-524452C6BF66}.Release|x86.Build.0 = Release|Win32 {930ECC6F-E823-4989-9FAE-524452C6BF66}.Release|x86.Deploy.0 = Release|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.ActiveCfg = Debug|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.Build.0 = Debug|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.ActiveCfg = Debug|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.Build.0 = Debug|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.ActiveCfg = Debug|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.Build.0 = Debug|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.ActiveCfg = Release|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.Build.0 = Release|ARM - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.ActiveCfg = Release|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.Build.0 = Release|x64 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.ActiveCfg = Release|Win32 - {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.Build.0 = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.ActiveCfg = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|ARM.Build.0 = Debug|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.ActiveCfg = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x64.Build.0 = Debug|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.ActiveCfg = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Debug|x86.Build.0 = Debug|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.ActiveCfg = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|ARM.Build.0 = Release|ARM + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.ActiveCfg = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x64.Build.0 = Release|x64 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.ActiveCfg = Release|Win32 + {945B8F0E-AE5F-447C-933A-9D069532D3E4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj index 99722745..d300ce19 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/SimpleTriangleUWP12.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true @@ -109,7 +108,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -127,7 +126,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -145,7 +144,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -164,7 +163,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -183,7 +182,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 _DEBUG;%(PreprocessorDefinitions) @@ -201,7 +200,7 @@ pch.h $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + $(ProjectDir);$(IntermediateOutputPath);..\..\..\Kits\DirectXTK12\Inc;..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) Level4 NDEBUG;%(PreprocessorDefinitions) @@ -247,11 +246,6 @@ - - - {f4776924-619c-42c7-88b2-82c947ccc9e7} - - true @@ -282,6 +276,11 @@ Vertex + + + {945b8f0e-ae5f-447c-933a-9d069532d3e4} + + diff --git a/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h b/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h index d01c411a..686d28e6 100644 --- a/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h +++ b/Samples/IntroGraphics/SimpleTriangleUWP12/pch.h @@ -36,6 +36,7 @@ #endif #include "GamePad.h" +#include "GraphicsMemory.h" #include "Keyboard.h" #include "Mouse.h" diff --git a/Samples/System/CPUSets/CPUSets.vcxproj b/Samples/System/CPUSets/CPUSets.vcxproj index cf2d8990..c3c67399 100644 --- a/Samples/System/CPUSets/CPUSets.vcxproj +++ b/Samples/System/CPUSets/CPUSets.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/CollisionUWP/Collision.vcxproj b/Samples/System/CollisionUWP/Collision.vcxproj index 5105ccc0..e2d74cdd 100644 --- a/Samples/System/CollisionUWP/Collision.vcxproj +++ b/Samples/System/CollisionUWP/Collision.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/ExtendedExecutionUWP/Common/Assets/Logo.png b/Samples/System/ExtendedExecutionUWP/Common/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7e704a106b99487be0f1eded426e6c5a2c65a9 GIT binary patch literal 39826 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 YA}aUbQ|(Go1_lNOPgg&ebxsLQ0HMvfUjP6A literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/Common/Assets/SmallLogo.png b/Samples/System/ExtendedExecutionUWP/Common/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b09d91991638282fc2426bbfd4a517733ff15a GIT binary patch literal 23704 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 QcF+-zp00i_>zopr0N0Pd_W%F@ literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/Common/Assets/SplashScreen.png b/Samples/System/ExtendedExecutionUWP/Common/Assets/SplashScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c352b156fd090a57aec7da81b3b19a3fb5888b43 GIT binary patch literal 26474 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 omdKI;Vst01?W$S^xk5 literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/Common/Assets/StoreLogo.png b/Samples/System/ExtendedExecutionUWP/Common/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..315472e10b9d380e509b2f041ea9ace5f994f5d2 GIT binary patch literal 24268 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 literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/Common/Assets/WideLogo.png b/Samples/System/ExtendedExecutionUWP/Common/Assets/WideLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c70f68e2c59214e0ff54844ccd8ae5e955826e10 GIT binary patch literal 46540 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 literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.cpp b/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.cpp new file mode 100644 index 00000000..ba23c3af --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.cpp @@ -0,0 +1,593 @@ +// +// DeviceResources.cpp - A wrapper for the Direct3D 11 device and swapchain +// (requires DirectX 11.3 Runtime) +// + + +#include "pch.h" +#include "DeviceResources.h" + +using namespace DirectX; + +using Microsoft::WRL::ComPtr; + +namespace +{ +#if defined(_DEBUG) + // Check for SDK Layer support. + inline bool SdkLayersAvailable() + { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); + } +#endif + + inline DXGI_FORMAT NoSRGB(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_UNORM; + default: return fmt; + } + } +}; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat, UINT backBufferCount, D3D_FEATURE_LEVEL minFeatureLevel) : + m_screenViewport{}, + m_backBufferFormat(backBufferFormat), + m_depthBufferFormat(depthBufferFormat), + m_backBufferCount(backBufferCount), + m_d3dMinFeatureLevel(minFeatureLevel), + m_window(nullptr), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1), + m_rotation(DXGI_MODE_ROTATION_IDENTITY), + m_outputSize{0, 0, 1, 1}, + m_orientationTransform3D(ScreenRotation::Rotation0), + m_deviceNotify(nullptr) +{ +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } + else + { + OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); + } +#endif + + // Determine DirectX hardware feature levels this app will support. + static const D3D_FEATURE_LEVEL s_featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, + }; + + UINT featLevelCount = 0; + for (; featLevelCount < _countof(s_featureLevels); ++featLevelCount) + { + if (s_featureLevels[featLevelCount] < m_d3dMinFeatureLevel) + break; + } + + if (!featLevelCount) + { + throw std::out_of_range("minFeatureLevel too high"); + } + + ComPtr adapter; + GetHardwareAdapter(adapter.GetAddressOf()); + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + HRESULT hr = E_FAIL; + if (adapter) + { + hr = D3D11CreateDevice( + adapter.Get(), + D3D_DRIVER_TYPE_UNKNOWN, + 0, + creationFlags, // Set debug and Direct2D compatibility flags. + s_featureLevels, + featLevelCount, + D3D11_SDK_VERSION, + device.GetAddressOf(), // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + context.GetAddressOf() // Returns the device immediate context. + ); + } +#if defined(NDEBUG) + else + { + throw std::exception("No Direct3D hardware device found"); + } +#else + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + s_featureLevels, + featLevelCount, + D3D11_SDK_VERSION, + device.GetAddressOf(), + &m_d3dFeatureLevel, + context.GetAddressOf() + ); + + if (SUCCEEDED(hr)) + { + OutputDebugStringA("Direct3D Adapter - WARP\n"); + } + } +#endif + + DX::ThrowIfFailed(hr); + +#ifndef NDEBUG + ComPtr d3dDebug; + if (SUCCEEDED(device.As(&d3dDebug))) + { + ComPtr d3dInfoQueue; + if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue))) + { +#ifdef _DEBUG + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); + d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); +#endif + D3D11_MESSAGE_ID hide[] = + { + D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + }; + D3D11_INFO_QUEUE_FILTER filter; + memset(&filter, 0, sizeof(filter)); + filter.DenyList.NumIDs = _countof(hide); + filter.DenyList.pIDList = hide; + d3dInfoQueue->AddStorageFilterEntries(&filter); + } + } +#endif + + DX::ThrowIfFailed(device.As(&m_d3dDevice)); + DX::ThrowIfFailed(context.As(&m_d3dContext)); +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + if (!m_window) + { + throw std::exception("Call SetWindow with a valid CoreWindow pointer"); + } + + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_d3dContext->Flush(); + + // Determine the render target size in pixels. + UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); + UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); + DXGI_FORMAT backBufferFormat = NoSRGB(m_backBufferFormat); + + if (m_swapChain) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + m_backBufferCount, + backBufferWidth, + backBufferHeight, + backBufferFormat, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + + ComPtr dxgiFactory; + DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = backBufferWidth; + swapChainDesc.Height = backBufferHeight; + swapChainDesc.Format = backBufferFormat; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_backBufferCount; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + ComPtr swapChain; + DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow( + m_d3dDevice.Get(), + m_window, + &swapChainDesc, + nullptr, + swapChain.GetAddressOf() + )); + + DX::ThrowIfFailed(swapChain.As(&m_swapChain)); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + DX::ThrowIfFailed(dxgiDevice->SetMaximumFrameLatency(1)); + } + + // Set the proper orientation for the swap chain, and generate + // matrix transformations for rendering to the rotated swap chain. + switch (m_rotation) + { + default: + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + } + + DX::ThrowIfFailed(m_swapChain->SetRotation(m_rotation)); + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.GetAddressOf()))); + + CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2D, m_backBufferFormat); + DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + &renderTargetViewDesc, + m_d3dRenderTargetView.ReleaseAndGetAddressOf() + )); + + if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + m_depthBufferFormat, + backBufferWidth, + backBufferHeight, + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + depthStencil.GetAddressOf() + )); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + m_d3dDepthStencilView.ReleaseAndGetAddressOf() + )); + } + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + static_cast(backBufferWidth), + static_cast(backBufferHeight) + ); +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_window = window; + + m_outputSize.left = m_outputSize.top = 0; + m_outputSize.right = width; + m_outputSize.bottom = height; + + m_rotation = rotation; +} + +// This method is called when the window changes size +bool DX::DeviceResources::WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + RECT newRc; + newRc.left = newRc.top = 0; + newRc.right = width; + newRc.bottom = height; + if (newRc == m_outputSize && rotation == m_rotation) + { + return false; + } + + m_outputSize = newRc; + m_rotation = rotation; + CreateWindowSizeDependentResources(); + return true; +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr deviceAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(deviceAdapter.GetAddressOf())); + + ComPtr deviceFactory; + DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(deviceFactory.GetAddressOf()))); + + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, previousDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(currentFactory.GetAddressOf()))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, currentDefaultAdapter.GetAddressOf())); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart + || previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart + || FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { +#ifdef _DEBUG + OutputDebugStringA("Device Lost on ValidateDevice\n"); +#endif + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceLost(); + } + + m_d3dDepthStencilView.Reset(); + m_d3dRenderTargetView.Reset(); + m_swapChain.Reset(); + m_d3dContext.Reset(); + m_d3dDevice.Reset(); + +#ifdef _DEBUG + { + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } + } +#endif + + CreateDeviceResources(); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DX::DeviceResources::Trim() +{ + ComPtr dxgiDevice; + if (SUCCEEDED(m_d3dDevice.As(&dxgiDevice))) + { + dxgiDevice->Trim(); + } +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present(1, 0); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be entirely + // overwritten. If dirty or scroll rects are used, this call should be removed. + m_d3dContext->DiscardView(m_d3dRenderTargetView.Get()); + + if (m_d3dDepthStencilView) + { + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(m_d3dDepthStencilView.Get()); + } + + // If the device was removed either by a disconnection or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { +#ifdef _DEBUG + char buff[64] = {}; + sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); + OutputDebugStringA(buff); +#endif + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + } +} + +// This method acquires the first available hardware adapter. +// If no such adapter can be found, *ppAdapter will be set to nullptr. +void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter) +{ + *ppAdapter = nullptr; + + ComPtr dxgiFactory; +#ifdef _DEBUG + UINT creationFlags = 0; + + if (SdkLayersAvailable()) + { + creationFlags |= DXGI_CREATE_FACTORY_DEBUG; + } + + DX::ThrowIfFailed(CreateDXGIFactory2(creationFlags, IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); +#else + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); +#endif + + ComPtr adapter; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) + { + DXGI_ADAPTER_DESC1 desc; + adapter->GetDesc1(&desc); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + continue; + } + +#ifdef _DEBUG + WCHAR buff[256] = {}; + swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); + OutputDebugStringW(buff); +#endif + + break; + } + + *ppAdapter = adapter.Detach(); +} \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.h b/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.h new file mode 100644 index 00000000..1da562ca --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/Common/DeviceResources.h @@ -0,0 +1,83 @@ +// +// DeviceResources.h - A wrapper for the Direct3D 11 device and swapchain +// + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D24_UNORM_S8_UINT, + UINT backBufferCount = 2, + D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_9_3); + + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void SetWindow(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + bool WindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } + void Trim(); + void Present(); + + // Device Accessors. + RECT GetOutputSize() const { return m_outputSize; } + DXGI_MODE_ROTATION GetRotation() const { return m_rotation; } + + // Direct3D Accessors. + ID3D11Device2* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext2* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } + DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + UINT GetBackBufferCount() const { return m_backBufferCount; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + private: + void GetHardwareAdapter(IDXGIAdapter1** ppAdapter); + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct3D properties. + DXGI_FORMAT m_backBufferFormat; + DXGI_FORMAT m_depthBufferFormat; + UINT m_backBufferCount; + D3D_FEATURE_LEVEL m_d3dMinFeatureLevel; + + // Cached device properties. + IUnknown* m_window; + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + DXGI_MODE_ROTATION m_rotation; + RECT m_outputSize; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/Common/StepTimer.h b/Samples/System/ExtendedExecutionUWP/Common/StepTimer.h new file mode 100644 index 00000000..e6f7acf5 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/Common/StepTimer.h @@ -0,0 +1,188 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// + +#pragma once + +#include +#include + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception( "QueryPerformanceFrequency" ); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception("QueryPerformanceCounter"); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception( "QueryPerformanceCounter" ); + } + + uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.cpp b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.cpp new file mode 100644 index 00000000..88252cd6 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.cpp @@ -0,0 +1,340 @@ +//-------------------------------------------------------------------------------------- +// ExtendedExecutionOnSuspend.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "ExtendedExecutionOnSuspend.h" +#include + +using namespace DirectX; +using namespace Windows::ApplicationModel; +using namespace Windows::UI::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::ApplicationModel::ExtendedExecution; +using namespace Windows::Foundation; + +Sample::Sample() : + m_showToasts(false), + m_consoleIsValid(false), + m_extensionActive(false), + m_pingEveryTenSeconds(false) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + m_deviceResources->RegisterDeviceNotify(this); + m_console = std::make_unique(); +} + +void Sample::ShowInstructions() +{ + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Extended Execution On Suspend Sample")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle Windows notifications with A button or 'N' key (default is off)")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle a log event every 10 seconds with Y button or 'P' key (default is off)")); +} + +void Sample::LogEvent(const wchar_t* primaryLog, const wchar_t* secondaryData) +{ + unsigned int tid = GetCurrentThreadId(); + SYSTEMTIME curTime; + GetSystemTime(&curTime); + + wchar_t timeAndTid[25] = {}; + swprintf_s(timeAndTid, L"[%02d:%02d:%02d:%03d](%d)", curTime.wHour, curTime.wMinute, curTime.wSecond, curTime.wMilliseconds, tid); + Platform::String^ LogLine = ref new Platform::String(timeAndTid) + " " + ref new Platform::String(primaryLog) + " " + ref new Platform::String(secondaryData); + + //Output to Debug Console. + OutputDebugStringW(LogLine->Data()); + OutputDebugStringW(L"\n"); + + //Output to screen. We must cache screen logs if a log occurs when there is no valid screen console yet. + if (!m_consoleIsValid) + { + m_logCache.insert(m_logCache.begin(), LogLine); + } + else + { + m_console->WriteLine(LogLine->Data()); + } + + //Output to Windows Notification Center. + if (m_showToasts) + { + m_toastManager->Show(primaryLog, secondaryData, timeAndTid); + } +} + +void Sample::RequestExtensionOnSuspend(ExtendedExecutionSession^ session) +{ + LogEvent(L"Requesting Extended Execution during suspension..."); + IAsyncOperation^ request = session->RequestExtensionAsync(); + + auto requestExtensionTask = concurrency::create_task(request); + requestExtensionTask.then([this](ExtendedExecutionResult result) + { + if (result == ExtendedExecutionResult::Allowed) + { + SetExtensionActive(true); + LogEvent(L"Extension Request During Suspend Completed.", L"Extension Allowed"); + } + else //Denied + { + LogEvent(L"Extension Request During Suspend Completed.", L"Extension Denied"); + } + }).wait(); +} + +void Sample::ToggleNotifications() +{ + m_showToasts = !m_showToasts; + if (m_showToasts) + { + LogEvent(L"Will log to Windows notifications."); + } + else + { + LogEvent(L"Will not log to Windows notifications."); + } +} + +void Sample::TogglePing() +{ + m_pingEveryTenSeconds = !m_pingEveryTenSeconds; + if (m_pingEveryTenSeconds) + { + //Creating a thread to handle the ping every 10 seconds. We cannot perform this operation during the normal update function + //because an extension requested during suspending will not result in the CoreWindow thread returning from the OnSuspending event + //handler. This logging thread represents the app's ability to continue doing work during an extended execution requested during + //the suspend event. + concurrency::create_task([this]() + { + while (m_pingEveryTenSeconds) + { + LogEvent(L"Logging every ten seconds."); + Sleep(10000); + } + }); + LogEvent(L"Will log an event every ten seconds."); + } + else + { + LogEvent(L"Will stop logging every ten seconds."); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_toastManager = std::make_unique (); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const&) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + ToggleNotifications(); + } + if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + TogglePing(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_keyboardButtons.IsKeyPressed(Keyboard::N)) + { + ToggleNotifications(); + } + if (m_keyboardButtons.IsKeyPressed(Keyboard::P)) + { + TogglePing(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + m_console->Render(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetBackBufferRenderTargetView(); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending(ExtendedExecutionSession^ session) +{ + RequestExtensionOnSuspend(session); + while (m_extensionActive) + { + //Once the suspend operation is completed by returning from this OnSuspending function and calling Complete on the suspend deferral + //the app will be suspended. The extension is only active while we do not complete suspending. This busy loop will prevent us from being + //suspended as long as our extension request was allowed and while the extension has not been revoked. If the extension was not allowed + //we would need to complete suspending within the normal timeout. Once the extension is revoked we also need to complete suspending within + //the normal timeout regardless of whether it is revoked by a resume or system policy. In the case of a revoke due to being resumed we will + //still be suspended but immediately resumed. + } + + LogEvent(L"Completing suspend."); + + auto context = m_deviceResources->GetD3DDeviceContext(); + context->ClearState(); + + m_deviceResources->Trim(); +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + m_console->RestoreDevice(m_deviceResources->GetD3DDeviceContext(), L"Courier_16.spritefont", L"ATGSampleBackground.DDS"); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + m_console->SetWindow(m_deviceResources->GetOutputSize(), true); + //Now that the Console is valid we can flush any logs to the console. + m_consoleIsValid = true; + while (!m_logCache.empty()) + { + m_console->WriteLine(m_logCache.back()->Data()); + m_logCache.pop_back(); + } +} + +void Sample::OnDeviceLost() +{ + m_consoleIsValid = false; + m_console->ReleaseDevice(); +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.h b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.h new file mode 100644 index 00000000..30268ff9 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.h @@ -0,0 +1,86 @@ +//-------------------------------------------------------------------------------------- +// ExtendedExecutionOnSuspend.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "..\Common\DeviceResources.h" +#include "..\Common\StepTimer.h" + +#include "ToastManager.h" +#include "TextConsole.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(); + + // Initialization and management + void Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession^ session); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + + //SampleFunctions + void ShowInstructions(); + void LogEvent(const wchar_t* primaryLog, const wchar_t* secondaryData = L""); + void SetExtensionActive(bool isActive) { m_extensionActive = isActive; } + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + + // Sample Specific + void ToggleNotifications(); + void TogglePing(); + void RequestExtensionOnSuspend(Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession^ session); + + std::unique_ptr m_console; + std::unique_ptr m_toastManager; + bool m_showToasts; + bool m_consoleIsValid; + std::vector m_logCache; + bool m_extensionActive; + bool m_pingEveryTenSeconds; +}; \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj new file mode 100644 index 00000000..5647a540 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj @@ -0,0 +1,275 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {a7adabda-e6fd-447c-8589-7c3260ad790c} + DirectXApp + ExtendedExecutionOnSuspend + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + ExtendedExecutionOnSuspend_TemporaryKey.pfx + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + true + true + + + + + + + + Assets\Logo.png + + + Assets\SmallLogo.png + + + Assets\SplashScreen.png + + + Assets\StoreLogo.png + + + Assets\WideLogo.png + + + + + {f4776924-619c-42c7-88b2-82c947ccc9e7} + + + + + + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj.filters b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj.filters new file mode 100644 index 00000000..a7531203 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend.vcxproj.filters @@ -0,0 +1,75 @@ + + + + + e78e95ac-2cf7-4541-abbd-fe905a3c6622 + + + 2aa1ca82-5735-4a6a-b2ed-e1485fa82670 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {0006e2a2-7c80-406e-abe9-b704daa8ef9e} + + + {82a56344-6fc8-460b-a4f5-48174d67ad37} + + + + + + + ATG Tool Kit + + + ATG Tool Kit + + + Common + + + Common + + + + + + + + ATG Tool Kit + + + Common + + + + + Media + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + Media + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend_TemporaryKey.pfx b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/ExtendedExecutionOnSuspend_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..a08eccad5938b0f29ee946fd443181aaa93160ad GIT binary patch literal 2452 zcmXqL;+(+5$ZXKW>BGjU)#lOmotKfFaX}NOElU%pr9l&?sX-I#FBB=(*DOt}&kdSb z9~(5W-e=>6>f+&IWLnU~^3R}&<(GjB8y8HNk=cNch2zq`pEKCBeG8eG*e|d&vE11C z!|0vRiqa#e`D_FKI-C~X+}J0Z?C>q!&+S2elJ3;C0h^Ak-+pxV=2LS0A{!^xT@EgG zxBIg-iscHMr^_>5x8?pZOB|>2IA8pJAYN^4eEE;RSE-%oP{U2J~70(*=qvTGI;=Co3#3biD;c*ep+`awE zlw#2reNS8^o`3PG$oVV!pF=6CRC|#|fl$DMhFzllrh(xb7e$;lvpX{(Wya>fqiL!A zJ0`4Pws9y}()Or6NB2n4vE51Kd-zK-U#_h9>w8AwvZ}V`s)eEgiw`b+8T%^WWyM*K zn3oc#e>h~FUp33{*g-GFnk|R<4&U=_ zcyGu>c86Hrp7cygJMZ~i?qU-giG#C*SICqru!slN8XT&(`tVucT-B+HLY1LD}7gtxL%ubVD>IQaWRJgO=+i`9@$Sddv36QNq$C^hwc*c#BZadcEi{tKG7D!}c(AKkYQN=zzfmf2H8T6buy zkx~=nzx`Bx5yR`^Y1&l^UcH%BtTzPxisr9jtls)!Ua7H?-SRJD`)BTd_9Cg;YR~rN z46}j{p9#0}RIoDbzwDCZnX+xY*Uo?OYvcc(>DT|nHKis>3CWlM ze%H&dYS?(zKp0+Ja*7(Vv9K^QFfbT|BLqbZz2rO?5*Z8`k{C=F5*f@GOc~M`bQ#hZ z3>i!r5*c(EOc)FpOc^X0bQuyEEE!T5Oc-<-QW?w`5*aKQOc>G_EErN5Oc)FqQWz2q zV%a#g*%(BO}9n&KBdDR(u{yY93F# zbFY1?Tz{F3Vc+tF%reSuGa`&O3vNtiPcwb+&n_%7V8TKkbz`IH{x&VLl}C-Pi|k}+ zI#S>BO6}vV9fpzHFYdfL_eIX-ikW*9?z}&<%KD0*Xxv(PhU$xKYd5T%c&7Tpyocg! znX6ptR%gxJACg(dF!uq!T$6!v?*)dk^&Dp%mcO(zQI9P@b4Mt5VQTN$I$^t-%d@gr z=I06|AO6DLZ*s8s#23DuAEUPJs7y@jiu27%%7}f_$onQDDnI|em3W!=?W3o(i$p)( zO+EMaMUZlU#nE;2Y6d)P%%QTvjEw(Tm<$*U#6Ub%5Rb=zi;Y8@jggg=otYUqEV)@hVadoaQLf|q zob?iKEC0qnc+OW6$M@Xd+A@CX;}0f%l^zLaOSPp_=I`n8xLX!fezV=XQt0TL)G)iP zn_Q=B>s%<0W3$QcTI_Z7$y;T{L~Bz;=h>o%Gh+^>GC!<8&b8!I;az6GzqeWZr@C;R zI$4umd9C;M+2{}ZSqgXkaoH$Zt(cbabJ?`3;rk24l(z1=tD^q*g6mI)iag2Nyo}p3 zi*AMRK5F~Yx+BpyBrpC}TiyJ=_(F<*$_7MQbn(r?F literal 0 HcmV?d00001 diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Main.cpp b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Main.cpp new file mode 100644 index 00000000..c2dd3cd6 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Main.cpp @@ -0,0 +1,390 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// This file has been modified to facilitate the Extended Execution sample. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "ExtendedExecutionOnSuspend.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; +using namespace Windows::ApplicationModel::ExtendedExecution; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_sample = std::make_unique(); + m_sample->ShowInstructions(); + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + if (m_visible) + { + m_sample->Tick(); + + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + m_sample->LogEvent(L"OnActivated()", args->Kind.ToString()->Data()); + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + //We use a deferral when suspending so we can wait() on the result of the extended execution request. calling wait() on the + //core window thread will throw an exception. + concurrency::create_task([this, deferral]() + { + auto session = ref new ExtendedExecutionSession(); + //This must be set to SavingData otherwise the extension request will be denied during a suspension. + session->Reason = ExtendedExecutionReason::SavingData; + session->Description = "Testing Extended Execution behavior with a request during suspension."; + session->Revoked += ref new TypedEventHandler(this, &ViewProvider::ExtensionRevokedHandler); + + m_sample->LogEvent(L"OnSuspending()", L"using a deferral"); + m_sample->OnSuspending(session); + deferral->Complete(); + }); + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->LogEvent(L"OnResuming()"); + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + HandleWindowSizeChanged(); + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + { + m_sample->LogEvent(L"OnVisibilityChanged()", L"Visible"); + m_sample->OnActivated(); + } + else + { + m_sample->LogEvent(L"OnVisibilityChanged()", L"Not Visible"); + m_sample->OnDeactivated(); + } + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + + void ExtensionRevokedHandler(Platform::Object^ obj, ExtendedExecutionRevokedEventArgs^ args) + { + m_sample->SetExtensionActive(false); + if (args->Reason == ExtendedExecutionRevokedReason::Resumed) + { + m_sample->LogEvent(L"Extension Revoked.", L"Reason = Resumed"); + } + else if (args->Reason == ExtendedExecutionRevokedReason::SystemPolicy) + { + m_sample->LogEvent(L"Extension Revoked.", L"Reason = SystemPolicy"); + } + } + +private: + bool m_exit; + bool m_visible; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Package.appxmanifest b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Package.appxmanifest new file mode 100644 index 00000000..6a294e03 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/Package.appxmanifest @@ -0,0 +1,28 @@ + + + + + + ExtendedExecutionOnSuspend + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.cpp b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.cpp new file mode 100644 index 00000000..851c81be --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.cpp @@ -0,0 +1,10 @@ +//-------------------------------------------------------------------------------------- +// pch.cpp +// +// Include the standard header and generate the precompiled header. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.h b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.h new file mode 100644 index 00000000..2f0437db --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionOnSuspend/pch.h @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------------------------- +// pch.h +// +// Header for standard system include files. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +// Use the C++ standard templated min/max +#define NOMINMAX + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "DDSTextureLoader.h" +#include "GamePad.h" +#include "Keyboard.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/ExtendedExecutionUWP.sln b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionUWP.sln new file mode 100644 index 00000000..8d2dbe03 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/ExtendedExecutionUWP.sln @@ -0,0 +1,74 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtendedExecutionOnSuspend", "ExtendedExecutionOnSuspend\ExtendedExecutionOnSuspend.vcxproj", "{A7ADABDA-E6FD-447C-8589-7C3260AD790C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DirectXTK", "..\..\..\Kits\DirectXTK\DirectXTK_Windows10.vcxproj", "{F4776924-619C-42C7-88B2-82C947CCC9E7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PreemptiveExtendedExecution", "PreemptiveExtendedExecution\PreemptiveExtendedExecution.vcxproj", "{AE64761E-2806-482C-96AE-B35C9F9D35D2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|ARM.ActiveCfg = Debug|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|ARM.Build.0 = Debug|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|ARM.Deploy.0 = Debug|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x64.ActiveCfg = Debug|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x64.Build.0 = Debug|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x64.Deploy.0 = Debug|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x86.ActiveCfg = Debug|Win32 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x86.Build.0 = Debug|Win32 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Debug|x86.Deploy.0 = Debug|Win32 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|ARM.ActiveCfg = Release|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|ARM.Build.0 = Release|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|ARM.Deploy.0 = Release|ARM + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x64.ActiveCfg = Release|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x64.Build.0 = Release|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x64.Deploy.0 = Release|x64 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x86.ActiveCfg = Release|Win32 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x86.Build.0 = Release|Win32 + {A7ADABDA-E6FD-447C-8589-7C3260AD790C}.Release|x86.Deploy.0 = Release|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.ActiveCfg = Debug|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|ARM.Build.0 = Debug|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.ActiveCfg = Debug|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x64.Build.0 = Debug|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.ActiveCfg = Debug|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Debug|x86.Build.0 = Debug|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.ActiveCfg = Release|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|ARM.Build.0 = Release|ARM + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.ActiveCfg = Release|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x64.Build.0 = Release|x64 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.ActiveCfg = Release|Win32 + {F4776924-619C-42C7-88B2-82C947CCC9E7}.Release|x86.Build.0 = Release|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|ARM.ActiveCfg = Debug|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|ARM.Build.0 = Debug|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|ARM.Deploy.0 = Debug|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x64.ActiveCfg = Debug|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x64.Build.0 = Debug|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x64.Deploy.0 = Debug|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x86.ActiveCfg = Debug|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x86.Build.0 = Debug|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Debug|x86.Deploy.0 = Debug|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|ARM.ActiveCfg = Release|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|ARM.Build.0 = Release|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|ARM.Deploy.0 = Release|ARM + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x64.ActiveCfg = Release|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x64.Build.0 = Release|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x64.Deploy.0 = Release|x64 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x86.ActiveCfg = Release|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x86.Build.0 = Release|Win32 + {AE64761E-2806-482C-96AE-B35C9F9D35D2}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Main.cpp b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Main.cpp new file mode 100644 index 00000000..f1c3bd0e --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Main.cpp @@ -0,0 +1,388 @@ +//-------------------------------------------------------------------------------------- +// Main.cpp +// +// Entry point for Universal Windows Platform (UWP) app. +// +// This file has been modified to facilitate the Extended Execution sample. +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "PreemptiveExtendedExecution.h" + +#include + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::UI::ViewManagement; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace DirectX; +using namespace Windows::ApplicationModel::ExtendedExecution; + +ref class ViewProvider sealed : public IFrameworkView +{ +public: + ViewProvider() : + m_exit(false), + m_visible(true), + m_DPI(96.f), + m_logicalWidth(800.f), + m_logicalHeight(600.f), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None) + { + } + + // IFrameworkView methods + virtual void Initialize(CoreApplicationView^ applicationView) + { + applicationView->Activated += ref new + TypedEventHandler(this, &ViewProvider::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler(this, &ViewProvider::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &ViewProvider::OnResuming); + + m_session = ref new ExtendedExecutionSession(); + //This must be set to either Unspecified or LocationTracking otherwise the extension request will be denied for a preemptive request. + m_session->Reason = ExtendedExecutionReason::Unspecified; + m_session->Description = "Testing Extended Execution behavior with a preemptive request."; + m_session->Revoked += ref new TypedEventHandler(this, &ViewProvider::ExtensionRevokedHandler); + + m_sample = std::make_unique(m_session); + m_sample->ShowInstructions(); + } + + virtual void Uninitialize() + { + m_sample.reset(); + } + + virtual void SetWindow(CoreWindow^ window) + { + window->SizeChanged += + ref new TypedEventHandler(this, &ViewProvider::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler(this, &ViewProvider::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler(this, &ViewProvider::OnWindowClosed); + + auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; + + dispatcher->AcceleratorKeyActivated += + ref new TypedEventHandler(this, &ViewProvider::OnAcceleratorKeyActivated); + + auto currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &ViewProvider::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &ViewProvider::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &ViewProvider::OnDisplayContentsInvalidated); + + m_DPI = currentDisplayInformation->LogicalDpi; + + m_logicalWidth = window->Bounds.Width; + m_logicalHeight = window->Bounds.Height; + + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->Initialize(reinterpret_cast(window), + outputWidth, outputHeight, rotation ); + } + + virtual void Load(Platform::String^ entryPoint) + { + } + + virtual void Run() + { + while (!m_exit) + { + m_sample->Tick(); + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + } + } + +protected: + // Event handlers + void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) + { + if (args->Kind == ActivationKind::Launch) + { + auto launchArgs = static_cast(args); + + if (launchArgs->PrelaunchActivated) + { + // Opt-out of Prelaunch + CoreApplication::Exit(); + return; + } + } + + int w, h; + m_sample->GetDefaultSize(w, h); + + m_DPI = DisplayInformation::GetForCurrentView()->LogicalDpi; + + ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + // Change to ApplicationViewWindowingMode::FullScreen to default to full screen + + auto desiredSize = Size(ConvertPixelsToDips(w), ConvertPixelsToDips(h)); + + ApplicationView::PreferredLaunchViewSize = desiredSize; + + auto view = ApplicationView::GetForCurrentView(); + + auto minSize = Size(ConvertPixelsToDips(320), ConvertPixelsToDips(200)); + + view->SetPreferredMinSize(minSize); + + m_sample->LogEvent(L"OnActivated()", args->Kind.ToString()->Data()); + CoreWindow::GetForCurrentThread()->Activate(); + + view->FullScreenSystemOverlayMode = FullScreenSystemOverlayMode::Minimal; + + view->TryResizeView(desiredSize); + } + + void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) + { + if (m_sample->GetUseDeferral()) + { + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + concurrency::create_task([this, deferral]() + { + m_sample->LogEvent(L"OnSuspending()", L"using a deferral"); + m_sample->OnSuspending(); + deferral->Complete(); + }); + } + else + { + m_sample->LogEvent(L"OnSuspending()", L"not using a deferral"); + m_sample->OnSuspending(); + } + } + + void OnResuming(Platform::Object^ sender, Platform::Object^ args) + { + m_sample->LogEvent(L"OnResuming()"); + m_sample->OnResuming(); + } + + void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) + { + m_logicalWidth = sender->Bounds.Width; + m_logicalHeight = sender->Bounds.Height; + + HandleWindowSizeChanged(); + } + + void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) + { + m_visible = args->Visible; + if (m_visible) + { + m_sample->LogEvent(L"OnVisibilityChanged()", L"Visible"); + m_sample->OnActivated(); + } + else + { + m_sample->LogEvent(L"OnVisibilityChanged()", L"Not Visible"); + m_sample->OnDeactivated(); + } + } + + void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) + { + m_exit = true; + } + + void OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) + { + if (args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown + && args->VirtualKey == VirtualKey::Enter + && args->KeyStatus.IsMenuKeyDown + && !args->KeyStatus.WasKeyDown) + { + // Implements the classic ALT+ENTER fullscreen toggle + auto view = ApplicationView::GetForCurrentView(); + + if (view->IsFullScreenMode) + view->ExitFullScreenMode(); + else + view->TryEnterFullScreenMode(); + + args->Handled = true; + } + } + + void OnDpiChanged(DisplayInformation^ sender, Object^ args) + { + m_DPI = sender->LogicalDpi; + + HandleWindowSizeChanged(); + } + + void OnOrientationChanged(DisplayInformation^ sender, Object^ args) + { + m_currentOrientation = sender->CurrentOrientation; + + HandleWindowSizeChanged(); + } + + void OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) + { + m_sample->ValidateDevice(); + } + + void ExtensionRevokedHandler(Platform::Object^ obj, ExtendedExecutionRevokedEventArgs^ args) + { + if (args->Reason == ExtendedExecutionRevokedReason::Resumed) + { + m_sample->LogEvent(L"Extension Revoked.", L"Reason = Resumed"); + } + else if (args->Reason == ExtendedExecutionRevokedReason::SystemPolicy) + { + m_sample->LogEvent(L"Extension Revoked.", L"Reason = SystemPolicy"); + } + } + +private: + bool m_exit; + bool m_visible; + float m_DPI; + float m_logicalWidth; + float m_logicalHeight; + std::unique_ptr m_sample; + Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession^ m_session; + + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + + inline int ConvertDipsToPixels(float dips) const + { + return int(dips * m_DPI / 96.f + 0.5f); + } + + inline float ConvertPixelsToDips(int pixels) const + { + return (float(pixels) * 96.f / m_DPI); + } + + DXGI_MODE_ROTATION ComputeDisplayRotation() const + { + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + + return rotation; + } + + void HandleWindowSizeChanged() + { + int outputWidth = ConvertDipsToPixels(m_logicalWidth); + int outputHeight = ConvertDipsToPixels(m_logicalHeight); + + DXGI_MODE_ROTATION rotation = ComputeDisplayRotation(); + + if (rotation == DXGI_MODE_ROTATION_ROTATE90 || rotation == DXGI_MODE_ROTATION_ROTATE270) + { + std::swap(outputWidth, outputHeight); + } + + m_sample->OnWindowSizeChanged(outputWidth, outputHeight, rotation); + } +}; + +ref class ViewProviderFactory : IFrameworkViewSource +{ +public: + virtual IFrameworkView^ CreateView() + { + return ref new ViewProvider(); + } +}; + + +// Entry point +[Platform::MTAThread] +int main(Platform::Array^ argv) +{ + UNREFERENCED_PARAMETER(argv); + + auto viewProviderFactory = ref new ViewProviderFactory(); + CoreApplication::Run(viewProviderFactory); + return 0; +} diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Package.appxmanifest b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Package.appxmanifest new file mode 100644 index 00000000..955bad1c --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/Package.appxmanifest @@ -0,0 +1,28 @@ + + + + + + PreemptiveExtendedExecution + Xbox Advanced Technology Group + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.cpp b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.cpp new file mode 100644 index 00000000..c0b9e1d1 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.cpp @@ -0,0 +1,345 @@ +//-------------------------------------------------------------------------------------- +// PreemptiveExtendedExecution.cpp +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "pch.h" +#include "PreemptiveExtendedExecution.h" +#include + +using namespace DirectX; +using namespace Windows::ApplicationModel; +using namespace Windows::UI::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::ApplicationModel::ExtendedExecution; +using namespace Windows::Foundation; + +Sample::Sample(ExtendedExecutionSession^ session) : + m_useDeferral(false), + m_showToasts(false), + m_consoleIsValid(false), + m_pingEveryTenSeconds(false) +{ + m_deviceResources = std::make_unique(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + m_deviceResources->RegisterDeviceNotify(this); + m_console = std::make_unique(); + m_session = session; +} + +void Sample::ShowInstructions() +{ + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Preemptive Extended Execution Sample")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle Windows notifications with A button or 'N' key (default is off)")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle suspend deferral with B button or 'D' key (default is off)")); + m_logCache.insert(m_logCache.begin(), ref new Platform::String(L"Toggle a log event every 10 seconds with Y button or 'P' key (default is off)")); +} + +void Sample::LogEvent(const wchar_t* primaryLog, const wchar_t* secondaryData) +{ + unsigned int tid = GetCurrentThreadId(); + SYSTEMTIME curTime; + GetSystemTime(&curTime); + + wchar_t timeAndTid[25] = {}; + swprintf_s(timeAndTid, L"[%02d:%02d:%02d:%03d](%d)", curTime.wHour, curTime.wMinute, curTime.wSecond, curTime.wMilliseconds, tid); + Platform::String^ LogLine = ref new Platform::String(timeAndTid) + " " + ref new Platform::String(primaryLog) + " " + ref new Platform::String(secondaryData); + + //Output to Debug Console. + OutputDebugStringW(LogLine->Data()); + OutputDebugStringW(L"\n"); + + //Output to screen. We must cache screen logs if a log occurs when there is no valid screen console yet. + if (!m_consoleIsValid) + { + m_logCache.insert(m_logCache.begin(), LogLine); + } + else + { + m_console->WriteLine(LogLine->Data()); + } + + //Output to Windows Notification Center. + if (m_showToasts) + { + m_toastManager->Show(primaryLog, secondaryData, timeAndTid); + } +} + +void Sample::RequestPreemptiveExtension() +{ + LogEvent(L"Requesting Extended Execution preemptively..."); + IAsyncOperation^ request = m_session->RequestExtensionAsync(); + + auto requestExtensionTask = concurrency::create_task(request); + requestExtensionTask.then([this](ExtendedExecutionResult result) + { + if (result == ExtendedExecutionResult::Allowed) + { + LogEvent(L"Preemptive Extension Request Completed.", L"Extension Allowed"); + } + else //Denied + { + LogEvent(L"Preemptive Extension Request Completed.", L"Extension Denied"); + } + }); +} + +void Sample::ToggleNotifications() +{ + m_showToasts = !m_showToasts; + if (m_showToasts) + { + LogEvent(L"Will log to Windows notifications."); + } + else + { + LogEvent(L"Will not log to Windows notifications."); + } +} + +void Sample::ToggleDeferral() +{ + m_useDeferral = !m_useDeferral; + if (m_useDeferral) + { + LogEvent(L"Will use a suspend deferral."); + } + else + { + LogEvent(L"Will not use a suspend deferral."); + } +} + +void Sample::TogglePing() +{ + m_pingEveryTenSeconds = !m_pingEveryTenSeconds; + if (m_pingEveryTenSeconds) + { + LogEvent(L"Will log an event every ten seconds."); + } + else + { + LogEvent(L"Will stop logging every ten seconds."); + } +} + +// Initialize the Direct3D resources required to run. +void Sample::Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation) +{ + m_gamePad = std::make_unique(); + + m_keyboard = std::make_unique(); + m_keyboard->SetWindow(reinterpret_cast(window)); + + m_toastManager = std::make_unique (); + + m_deviceResources->SetWindow(window, width, height, rotation); + + m_deviceResources->CreateDeviceResources(); + CreateDeviceDependentResources(); + + m_deviceResources->CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); +} + +#pragma region Frame Update +// Executes basic render loop. +void Sample::Tick() +{ + m_timer.Tick([&]() + { + Update(m_timer); + }); + + Render(); +} + +// Updates the world. +void Sample::Update(DX::StepTimer const& timer) +{ + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Update"); + + static double pingTimer = 0; + if (m_pingEveryTenSeconds && timer.GetTotalSeconds() - pingTimer > 10) + { + LogEvent(L"Logging every ten seconds."); + pingTimer = timer.GetTotalSeconds(); + } + + auto pad = m_gamePad->GetState(0); + if (pad.IsConnected()) + { + m_gamePadButtons.Update(pad); + + if (pad.IsViewPressed()) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_gamePadButtons.a == GamePad::ButtonStateTracker::PRESSED) + { + ToggleNotifications(); + } + if (m_gamePadButtons.b == GamePad::ButtonStateTracker::PRESSED) + { + ToggleDeferral(); + } + if (m_gamePadButtons.y == GamePad::ButtonStateTracker::PRESSED) + { + TogglePing(); + } + } + else + { + m_gamePadButtons.Reset(); + } + + auto kb = m_keyboard->GetState(); + m_keyboardButtons.Update(kb); + + if (kb.Escape) + { + Windows::ApplicationModel::Core::CoreApplication::Exit(); + } + if (m_keyboardButtons.IsKeyPressed(Keyboard::N)) + { + ToggleNotifications(); + } + if (m_keyboardButtons.IsKeyPressed(Keyboard::D)) + { + ToggleDeferral(); + } + if (m_keyboardButtons.IsKeyPressed(Keyboard::P)) + { + TogglePing(); + } + + PIXEndEvent(); +} +#pragma endregion + +#pragma region Frame Render +// Draws the scene. +void Sample::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + + Clear(); + + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Render"); + + m_console->Render(); + + PIXEndEvent(context); + + // Show the new frame. + PIXBeginEvent(PIX_COLOR_DEFAULT, L"Present"); + m_deviceResources->Present(); + PIXEndEvent(); +} + +// Helper method to clear the back buffers. +void Sample::Clear() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + PIXBeginEvent(context, PIX_COLOR_DEFAULT, L"Clear"); + + // Clear the views. + auto renderTarget = m_deviceResources->GetBackBufferRenderTargetView(); + + context->OMSetRenderTargets(1, &renderTarget, nullptr); + + // Set the viewport. + auto viewport = m_deviceResources->GetScreenViewport(); + context->RSSetViewports(1, &viewport); + + PIXEndEvent(context); +} +#pragma endregion + +#pragma region Message Handlers +// Message handlers +void Sample::OnActivated() +{ + RequestPreemptiveExtension(); +} + +void Sample::OnDeactivated() +{ +} + +void Sample::OnSuspending() +{ + auto context = m_deviceResources->GetD3DDeviceContext(); + context->ClearState(); + + m_deviceResources->Trim(); +} + +void Sample::OnResuming() +{ + m_timer.ResetElapsedTime(); + m_gamePadButtons.Reset(); + m_keyboardButtons.Reset(); +} + +void Sample::OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation) +{ + if (!m_deviceResources->WindowSizeChanged(width, height, rotation)) + return; + + CreateWindowSizeDependentResources(); +} + +void Sample::ValidateDevice() +{ + m_deviceResources->ValidateDevice(); +} + +// Properties +void Sample::GetDefaultSize(int& width, int& height) const +{ + width = 1280; + height = 720; +} +#pragma endregion + +#pragma region Direct3D Resources +// These are the resources that depend on the device. +void Sample::CreateDeviceDependentResources() +{ + m_console->RestoreDevice(m_deviceResources->GetD3DDeviceContext(), L"Courier_16.spritefont", L"ATGSampleBackground.DDS"); +} + +// Allocate all memory resources that change on a window SizeChanged event. +void Sample::CreateWindowSizeDependentResources() +{ + m_console->SetWindow(m_deviceResources->GetOutputSize(), true); + //Now that the Console is valid we can flush any logs to the console. + m_consoleIsValid = true; + while (!m_logCache.empty()) + { + m_console->WriteLine(m_logCache.back()->Data()); + m_logCache.pop_back(); + } +} + +void Sample::OnDeviceLost() +{ + m_consoleIsValid = false; + m_console->ReleaseDevice(); +} + +void Sample::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + + CreateWindowSizeDependentResources(); +} +#pragma endregion diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.h b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.h new file mode 100644 index 00000000..d23efe7e --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.h @@ -0,0 +1,90 @@ +//-------------------------------------------------------------------------------------- +// PreemptiveExtendedExecution.h +// +// Advanced Technology Group (ATG) +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "..\Common\DeviceResources.h" +#include "..\Common\StepTimer.h" + +#include "ToastManager.h" +#include "TextConsole.h" + +// A basic sample implementation that creates a D3D11 device and +// provides a render loop. +class Sample : public DX::IDeviceNotify +{ +public: + + Sample(Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession^ session); + + // Initialization and management + void Initialize(IUnknown* window, int width, int height, DXGI_MODE_ROTATION rotation); + + // Basic render loop + void Tick(); + void Render(); + + // Rendering helpers + void Clear(); + + // IDeviceNotify + virtual void OnDeviceLost() override; + virtual void OnDeviceRestored() override; + + // Messages + void OnActivated(); + void OnDeactivated(); + void OnSuspending(); + void OnResuming(); + void OnWindowSizeChanged(int width, int height, DXGI_MODE_ROTATION rotation); + void ValidateDevice(); + + // Properties + void GetDefaultSize( int& width, int& height ) const; + + //SampleFunctions + void ShowInstructions(); + void LogEvent(const wchar_t* primaryLog, const wchar_t* secondaryData = L""); + bool GetUseDeferral() { return m_useDeferral; } + +private: + + void Update(DX::StepTimer const& timer); + + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + + // Device resources. + std::unique_ptr m_deviceResources; + + // Rendering loop timer. + DX::StepTimer m_timer; + + // Input devices. + std::unique_ptr m_gamePad; + std::unique_ptr m_keyboard; + + DirectX::GamePad::ButtonStateTracker m_gamePadButtons; + DirectX::Keyboard::KeyboardStateTracker m_keyboardButtons; + + // Sample Specific + void ToggleNotifications(); + void ToggleDeferral(); + void TogglePing(); + void RequestPreemptiveExtension(); + + std::unique_ptr m_console; + std::unique_ptr m_toastManager; + bool m_useDeferral; + bool m_showToasts; + bool m_consoleIsValid; + std::vector m_logCache; + bool m_pingEveryTenSeconds; + + Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession^ m_session; + +}; \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj new file mode 100644 index 00000000..8e4f1917 --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj @@ -0,0 +1,277 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {ae64761e-2806-482c-96ae-b35c9f9d35d2} + DirectXApp + PreemptiveExtendedExecution + en-US + 14.0 + true + Windows Store + 10.0.10586.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreemptiveExtendedExecution_TemporaryKey.pfx + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + StreamingSIMDExtensions2 + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + _DEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dxguid.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);..\..\..\..\Kits\DirectXTK\Inc;..\..\..\..\Kits\ATGTK;%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + Level4 + NDEBUG;%(PreprocessorDefinitions) + Fast + + + 4.0_level_9_3 + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + Designer + + + true + true + true + true + + + + + + + + Assets\Logo.png + + + Assets\SmallLogo.png + + + Assets\SplashScreen.png + + + Assets\StoreLogo.png + + + Assets\WideLogo.png + + + + + {f4776924-619c-42c7-88b2-82c947ccc9e7} + + + + + + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj.filters b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj.filters new file mode 100644 index 00000000..0cfb823a --- /dev/null +++ b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution.vcxproj.filters @@ -0,0 +1,75 @@ + + + + + 628a1e60-8c8e-4f88-96b0-c0285a8e0547 + + + 6d09c25a-79e5-42a3-bd04-4fcc0d3284f8 + bmp;dds;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {2027bc94-b028-4ee7-81c6-618f290f0cb9} + + + {85016833-bba2-48ac-88c8-c3f082f38b38} + + + + + + + Common + + + Common + + + ATG Tool Kit + + + ATG Tool Kit + + + + + + + + Common + + + ATG Tool Kit + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Media + + + + + + + + + Media + + + + \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution_TemporaryKey.pfx b/Samples/System/ExtendedExecutionUWP/PreemptiveExtendedExecution/PreemptiveExtendedExecution_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..fed812c45362fca6659efc0ac8a5cb78e292df25 GIT binary patch literal 2452 zcmXqL;+(+5$ZXKW>BGjU)#lOmotKfFaX}NOElU%pr9l&?sX-I#FBB=(*DOt}&kdSb z9~(5W-e=>6>f+&IWLnU~^3R}&<(GjB8y8HNk=cNcg`@gqV5EVL_yQ&-_6sacEH{40 zrJ4OaaBgd%)cg;}dhHl14Be)ky?eI7E?f1iPPk)6@;rkcwe4j^%q#h~{Jwp*P}$gh zcF76nO{ovweo1EaTK%mh@H;bWUxO^^ccxR#X+&&Ym;XDCu2%naib+sNVS-W#)WZf8vo* z=9*}h-g*90oV=G^Xi%)#6u&v+lbimwU=4t-2+t+iD-Qzi-#9 zBj4vJ#IQSVo8Ec1tj_pDae?h~=6UVSmlD72<+olwMJ!(VFw;`L9YVJ*McBTKoZ*~d zPP^^i-@>A#m`O`Svc_AZSH za9#gkpZdog2D{F^`s;q9DBI?n_Gzva-=wzq?-kx3q;zO@+O~H2>e}l@iia0!y;T1% zcRSF<^TKS_1nt#%sh?V2O*OZUx%t(9_D8v+Pt2Arz2kW%=Ye}vRr1T0N&mL;dN@ou zAGVTd+lxBiPSpuU6))dfExUZ@u!Pi9Rolq9p$5%*2d1t4(e~R{V(IyU`1><s!Gg_OX`|M-9tMoy?-cu`9 z1~%x`?>?|V-Ro~ywD|rwGoR>7*7jnVrDxw&&sPsl;t$bSJ4xZ#DTP^U{WDzlpD3Ra zG%-PEb+gx`c^iG^*p$>gc47!yEMKQSxiB}Utia-8{{v@^yG6gsYV0yP&jl=O>$zZ6 z-FIr;@0J;kMmZa11V-Hue^+cK&Z^M(giC5|{Ume06NMVPHs#*^xzBscy^Y5c0`)tzQymx9WqlN{yfpoHZOYf&)eZ==hsau{_;sEpmh4xrPUjEMo!_J(!Bpj z=AK(R)f=3Se_Z)@*$v@e_HJSCz9nq^^jUIIv-X7Sz(nc0rE~u)7ud4wirVP$&vD!J z)eW_$WA=JJ<}5xj`M=qL9R>xbPQFgAh^x~2P6P0uC zo85ihZFWiaF`J|#ys(MMsr}PV*UwL_C%NpH9{Gmn;wqt~=K~%Wd3sFaSgN?qRJP{A z&&}q%*Spo^O3!*}V;?=Tb~k3)QyFTf-MSH^FDq zt0PD66mHpT*m%}J7+zd*iW;)9urM+(Fc^d*1Vs$Jre1%_aT60k@fLpp;3gEK=BLnT82 zLkUAZLpnndLn1=~Lk3uv0z&{;T^U0rLkdGGLy6C)$TqkG&Mdjyo{u{}}FY4yuvUpzHu1h1U>>vq57TBjKAH$K;sn-f>FCq>I0 zQ{MJEbo!o0&vvd}dEc>qOVj-p5e2T}*Q}cfKe%<@!C%{N}}Y zW!6o0FKQ>0ZPw8*S)scxcxg48f4rpN8AkOx(?7c`Otw#ztykM2E5f$#h}zvsdvTvj z^&4tB+@~;j8-;4~Jm6(s$aBfMW4imSgR>*$`U4gO{hBJ-`=O_R`J#f+h2&L!oXXxW zOk1UDSQyt9g_ki*;+IV4@3{8mL}TOak2OzAA~eHqSJ*c;uGsGWG1PWxC=)Xy1LI;1 z12qF4Hs(-SVMfOPEKCLr24WzdDu~Bpz{SR)&Bn;e%FfJ;9G2YRuw-OdD%WjdK*bNuHnco@6jP)x!474k;AlzvYw zzkGh7+j`S8^3S$sm-*FiPOOeiSg=6k*N@NV?yZ^}wPM=e*ZXFin{xV{KKtS~>*j>L zJh8T=?a%e2-M^Afuov8A)-#{xbla6JKS9HEzJZ?4?q_nmi~N%fHa*?_rg`ZO`}AFX zml)ohGd?r?@9=D3Dso^fttzuUsejYRaT@q3?=(+Bte(i(G!4`JDBY|A+jC<{6x! z?@bLwv1fN{19<~>HdbvuW+o{X5kFh@EnN2cC57h-efD<7{#^AcwSq^XIoSng UCxsgwK3*jmd1hwV8BqHO03` + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +#include "DDSTextureLoader.h" +#include "GamePad.h" +#include "Keyboard.h" +#include "SpriteBatch.h" +#include "SpriteFont.h" + +namespace DX +{ + // Helper class for COM exceptions + class com_exception : public std::exception + { + public: + com_exception(HRESULT hr) : result(hr) {} + + virtual const char* what() const override + { + static char s_str[64] = { 0 }; + sprintf_s(s_str, "Failure with HRESULT of %08X", result); + return s_str; + } + + private: + HRESULT result; + }; + + // Helper utility converts D3D API failures into exceptions. + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + throw com_exception(hr); + } + } +} \ No newline at end of file diff --git a/Samples/System/ExtendedExecutionUWP/Readme.docx b/Samples/System/ExtendedExecutionUWP/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..9b4ff1f022502df23dd6849ab206c629e7802ce3 GIT binary patch literal 1502096 zcmWIWW@Zs#U}NB5U|>*W@U&dFV+A7v!z>O424MycrfBE%( z|K=55cH>y;%j%M&bkz9!J>xQ!^qTz_LpL$WPcfC;?boiuI5~Rd8Kva+o1Y)l^=9Hy zc1`6?$>DCi>#wJOZ1dXY2@`I$^i1t|*Y|nC^aZXSYnh#=9;(uv5cjvqdSZPC>xYX4 z6^Dzn1$g)jsy3YbA;`6HjX~wD3q`(<&NQj=m&W&;nsF&m{(9x=L(Zc6JX?yVo?;D} zyT0eoG1D8yOPAdF+7h(0z?IisDCud%fx^2{yRJnlO;YQ*w5az|xE1?)6_wzJA6+xD zo@BpPoo*JNCA54wXO!C(*M&tHUoM`lobAj}a$uL&>@KlWGH&*#5~o%1&6`rse<`Be ziRDh1z`uD5zP;^ZcMt#^b{yZX%@yz{m%noU{`@27o`tBC`t2=k zd>8b;c_V*#d4>RbI!RXa86>MIn0A&v)mOK5;TI{Qu9)fSSSOCQ5C8 z&%nUo$Hc(E&A`DFUzD0ttgiF<_&d+equbFf(>#zZj!~5pH%@_9u-a06;*iS$C z!flD0>>SaaKEk(eWL^LF*XG6zrr4K>?x!zZo_wLIc#d1?gDJ5eq^5=PcJ1Z7_A~Bq z^zS_t3{zY8EH$jSR`7^t_Oowke@`iUYMyHDjuh=WFU2Y}Mgh$l0m?yCyA0DC*zyu4j_= zX73dvx5Pipm!1>r_?Zz~{#cYK(%H<&z>vYkz#zlG!C0POl%fyGBq{mHrManjC7?75hP z{ocu{e||bWV=@1QWr0TOnR6y^q%5pZUOi{e+WGI(RE(y1o{LgdRJS%r*|}ry%>53h z*I1{#T4p@)wUV!2R`zapFWnVS^L=||Gbi1 zTjBSmYxmFBvF!g}u06F$^MR*mG~=Z>Nk{32X}jBe!V`*>8qD7)q!p@bJFPcfvN%!U zU0}xozbRg~OmANYr3;6jb%i69@fn;2r}u(k?7Fm61>tGq{)3N zzJ0#c;Yl1>O&fQM{RzEs{l#uk*mSqe^Tp{8$2%ssSP9N~^vUay_Dmk(qY{4&Y+G73yj#P*QJ-Jw z)e#Go!|FM4`gLLRIvQC_7u!!1oaGT<{!1~R-I*y&-@R+A-_bWKI&S&? zy7F_6^sju+KP+)&`+}TTKd!&ewyF7l-v0mj{~wqCe0&ivq)!M(?kAHxvyt0s63Wmw2W!C%E`qNb7uczQxf3W8!Tav{4H6Qmj`qh+`}6#m&vwvJYRNw-j-TQU--MMu#5;x7=Pq5=`?}U3 z^Ou&y_q_Q{p%=vazfG6j$$QM^%;}n#@_>#XO__Cn|GjwK@81z$r|~)F)5ox9pC4zt z{_lVDJMK_@)wiw6H;zAD=N!x*dGB9=|JU`4-ZtM9Kk?-|pJC|J>w9*#ZmfTw_c4F} zAC^DvSN@lzh3+%`|GUHB3xCBE&X37Q?H3(-|NYOUC0w6=JwNt;Qf6IpjKu%v3={S< zDYX5V-+aJc@j&9*y0&9?mi?bMoxk>TM*X6v|K(=Ih}&7yERWU7_84Bj^4O1EUvawW@0I&+7JfhRyJGvr zI`+8Rb;s`A%du~=IyLLxZC&|epV!^}9^U=;qSd=f?qdNjHfR5T!&iBA+Qyqa>v!hM z%}&xhcR9!2vgt5OqF-cMG{~vDN zWC@nHX}{NgS^b;sm+YIT`U$re@L#ga*u3BAn5V@5-zTPDpHxw4_58N+-$^QsN`pQQtor?o2{B`5g>*AK)J+{AYc_GVv-CvhkKCkQFC(i%=UYzNSzuRlf z-^WE>aoigJIQ&N4V!P$;ze+0RDfAzylQ;VvD^s(FZ>szJha!Ktzx-7?d*9*XL5Z5` zFaOm%_h>#}S@Fwo`PZ};&<7zzTEx&POay!S3h??{&zH&bKbW9)ouKCi_ZLz zKE252$8YX~>vIp@*W5h$(s7$TC35qu>VLJi?UPA<@5lG5q`&&t<(ca%?fJ}Vc>e!e zS*Iahv*oXW+@oc`zUBP+wfFw^`bwP{eTRR{`(^r6Q*M^g{?5wCeOCVOkH*}ruQt50 z!zS7I$Bo54*?IYrJJ}B`_uKs=^W=1ipF++19V@@r?RJc`|9|c5=Ku5lOlh!R`ytCV z@{{fDzR7pz{N6cnx>EhZcmdbyH+xEDHa!sAf7Czp-!?t{1JB>2-2c!1P5r?AV|9mX z&ec~w65VDm=KTNvQTwnxW%oLNAAh8E|MG?VOd9p?{>=NIx@3FiytC;|xAdd$@9|8| zP&T~(w~D9j;vLR6s&_QYYCh#``uukN{n_WQeb28}yYX+@AIp0Fr?n;LQ~pk#)BaBI zOZ7ROr&az8`e}DFUtK*|AXK^OYQFoS`+ZmXyRz@~?9cw5W%s=QX}Iytm)GvjY^Z#< z>-&Antmj`h{(n`F{D0o9FM($a)_>c*!2a6u=gBYM?s?v8r=NFW`~2&5^*TLOpZ$K+ zKmNA=`M&o`pCx9i)bsw^@;d#w=*?WY+Aa1O#rc1^kL+A8CI2^gx_XrD%*ro!p4|ND zDfL7=ea8En_fI@m{W0rvoS==U#k-TGKf=sowi$b$;dxuPf8Mf+c@Mu|j=y_9SA1IK zZ_&Q<-?sl#UUw*c)w`$CKaH;C?Y5=G7&yz{?yUE9X~;{xxc*i`R7i{JT7UUx(N=Woq+-e1BUYL0$hcj5YTZ`TjC z9pN0kwKi@y&wuE%ll_)Vq*%5{2@c2}LB_59=^ z4zHyAtpDMWKbBsPo*Z8M|F4hn`W%jbdUyYA`@hci-o#Hi|JVFDAYb}$wTsC2N!mP% z9)-5PoBsNI{j9Q{^rIW5@1M``sg5;)?WrVJ(*FJL9*6sWTzhkCHP^rF%AnWvyap`- z=hvHDOK1EW`m2WJ;kmEvj$|~!V_@w*Kr~d!PGu8e}FQx2!EB5p2Ze<>u z(@{LLjf^(`KOwe#NoY^O$^!;#j=f#3)l zF_^BM$JMW{JVmsu(AQW-ZqqlWk{?AfAp-0T3u+}cUK6>Nk!;=_rEvPT&3h-`U(=+z z&(56gvhVh@IU5~MeVLnnbk-9ArHxrFa|I(F2jF=cIp;?vwR$V;q2Vqfp&kK7REP3ymZ-mjq7%7 zGapmyyh*;NkMXJtSI@4UX!G;R*K;i$Q7=L&`PbcHI=y+>q373_*LSR)W3b-bN|{$O zxrQ;Wao^6uiXRc0zQPL`&K_>$U-#X8cJty$8HqObgOSPqZdLNI%~KKZ``(wd@%R15 z+#f7oEcBA}x>d4f{(QHz3CS=w7?-8y#miLU1+WK1**nIGS4%(8OxQG>L_ zZEa8P&wY2d z%1G<$m4}nOo~d=H*1XXV7u+^=^@6Nc@1I{qFI*IDYh?G|mMLB$9=cM*d)@2Tg2Lw?iK64Cq6hY>im9QnjP`RcFZ zlUb9lvuX&g6TNX-GP63^QqF7lUA>E9mfhBu7#IpRZ|i01+-5r8bb08(X%G24F1TL5 z|NVlAuDI3G?%7hSa*Z9TcHP?emha46(@L{=Dz&KpV1tvD>|aQ2m7jqd$?G0xED z#P?5c{JgQ8mr*-gWqp79EMH;$RTm<~^S{3ob6aKJ@{xPOh7T2UMAl4M#eOirwChxJ z%7e5uy|0oFJ)e1Fak8$CD!LZ zX8|Gkyw49V3fQ$E;EzL`wZ>lS@V1aDr#>m6O$+uNoSk`XR$a=i3u0F*KYb2c{IF?D z%0$H%pCh*I5ZnCc=eAG!2VADl{ghHNwa(+6fr7K1l!SKq!_IZ~@gZ4rH<-jfzErCa zczyZhzd1I2=92_hY`lM`Y3_&BkE_k94Guox%_!j8B)8_6c*2x|_eC<_o=642;=WKF4oBZB`@!08uFCWA`D@r+G z)pJs%aB|zUH;Xc@9hmkUP%iT+{pav)y2o+JnoZl7pDlRaZ7RrA8NqC+nzW5y`^j84 zOLv}a2?@S)J{asjf5|aL?d>7i^OG4{I3KPPKWegYqEP3e*{a{Ge0~_+>C=f=qbH=j zy+|T5iAB?~f>AEU|IWKrF-e&_Vvim1x8b`v=>ogFnEK**e4BdCE%K_WFkqkfv@`S? z%WsZ@&*x1Ksj&R8(;zKcWYNvvC!{Amd%|+7Nl=S%zuIXfCvJ_T)bzRPdb1xG7%FSe zxwNOK#lR&0RFJuO!^MOW<-N9l56k+mS8g-){Kd4!!i!b2?%1INQ}*_niq3i?^jJpi z=$9pR1@b8_-%gyFcG$q~^O|`QehItom@liV`(~7OUabA^_qo&gze%kv5el82_+Mvh zmza}F^%3@pA7?HflC650dD<^YP*mk?PV?;AUEPOm&uw7V`CK0M?cuM>ZJ8@&g!8AY z+;VI2(Zyy0Cd~FXFGqaWdFyJCoOsEr_~gv@vWEl@w6Z)`5}zn6uka>QfWQ64w2NOJ zitS-&pPgI%beZYWo|Og5o{9e|c`KN`F#Ms)x`l;SGv7`Px%SL2B{#xEFDa`$rLM-@cK?WugCSRcDvtvowVX?>|^69n;Dgi(@S3H=v>{)py=@SS?1DZ-m9u-lTU-%rire3$9Qd4H|9S69?mKe;+(yZ^!8N!8n4 zczv^US$Ba~@cQbbo31m@jrU*kiD|#a()YJ2M5aDn$9LGdJBfRd@aw-1?k4;Qa99=+ zY|1P1OMF4inVn6Ue@~yW`uB0&edfl^Y5HqlObt%IHrut;*6`lfWg8ck9)2UYLGQ{2 zUiZ9j?5y`+bUiF?rSHJ3L+!HeS+niG|pMTPmzg#;)8Kn44-%sGTo$})I6rNW?s!6-I zEt_}tSk>EE$G%2rY*gCD%db|d5;l41l&5JIa~C(Hb{16`e7w434}JOW8MfX@b&TCeiJeL*BTyrf!?jZW5H+Qg-*Qm+JByEwjGx zT#ysH#5C~$>$UPF0ebqp%TFC!^={&&zefUUZ{NO{xJF2F=dOtk9A_DK_8U6NnA<%& z!QLw|>-6*Xi-yKO4Yyb9PEG$E;jVvxXNf4+hxN}x&V`$Cimw%V`Ai{rJ5#6Lb(3$6 ztHa{uzUT-}$vhhO%&Tc=cEqS z72LlA-P-Qn`TRiksL<6HwyT%t>fPLCZ2QXTn#dBVO;_El(oQejGtciZw?Nw?9Z8QZ zADd^i&RN=JqO{N_!74VY^z_nwZf~Es~H5@RqVR8t6fIT zGdI5BU2`bsGU1K8-)6Tih|GQKcboZyuerTv_@yUCm(+PD$v5uZ#L%vIrRr&gaK^R5 zS5IUTUgmz-5G{M^vvuz@tKyTvRXjBv`%=Wamia1ZCT}-+b~IdXMJ1b$5!>%&_qvT5 z9J~Ld{M_I=Y0`ofm8UFf*nfy0&{bMe$9T*r{{4GH&-1e<_DL{Is*SewuIq1hKDu

MF(A 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Ý*anAOSRC` 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

84K6P0#)CCunt`$T22-?f`@ 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 z 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 z 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

f{pNj9LxA=Ay4dQ!U$6W7He0gy)pq&h z?fH1@eckunmEU%7u^#xjdH(-5x9|Ted*eAbdHW2}`_=ktyIyyn+Vktx>hJf;<8}81 zCC}wAeVWiy|LgMnqb}cXRbMyz(WAKI>EG|`_Wn7g{r!Hqyp5gFg}jcpphiqml=Q)h z_j|KbEFNqVJZNd~HT^-}u9t1cf+gV+9R8JHpNEEtUa0G_iS0C*UD;rrte?Y zs1?4L7gzJKm0e%YB=_x|P2Y1>w*EcAYhLr=-|wWVsQ8{emHy{r`uY0T#yai3vG?x$ ziH|s6oh{$^@gTeWo_h@4X{Xy~yo$H^@u2PKbp_oeEjxtw`N(dIUd3@|!6W?*95tcg z(_b#sn&I^F(!Lo*hk4~I?H2`9ZojoCQ>IXztE@_J(Mp+;H7y~36$|C2+Nzi5Qa`E_Qb%u|559z<%@lJBio`Qe3LMC1paNZ}l zifzZ7pUahRa!k9tCCuaPD%B+)baKn@Z?4)td%EHI;@RdE7cD0~tbF{{{M|0?(;o{> zHiT-ohc!P~czcHHYt2=zmuBbht9(AU{Fcd~B~^M6SFdi{QzqN>a)MjB(DDC|cE%ss z$rz&Jzw(jK;o|)}9)G*Nn|qd2?#_+=y@!uJf4}GRx7_V_-FBzv>4X((t=O<4*ZhRr zl`C%HjcY$wsh*kqKGf>D&Kj+&m$ihZKR3T$b9wj86TO}t4CYd~MRTw3y&)JO`*v@y z#eO%p@_!-a4(C$jH|N-Nw@r&qvimdhe2v<_f2-#_x^}2rtRpK?;mQAh-~ay&m;Z0U z9@YJP(Utf0|9|(_|9L#`U)d8KDc<>q6iUp3{`z6V5>yy`b z2U6#5|0{5<=h^Hi(}ycdK8A!yuZr4oT36EMkdNSwt^C}7)(CAC3*{5C?EJB+Q~UIt zOwGQi8y~ECrKV3^(e_3rzIOYM*lt~|&DH0&OGY1&{i4LB?ms>2=d6F}hk8vd4ySwl z{j8-bqulA%l5LY-d~I795%f9rr93lE5Iobl`4*7B#09y`n4+OFB)bjqS)-*oPP zMFv@KX0G$ie7|q`FV^yy>hE`N+;EFX$eFWi@ArGv@xMMzpI2$-_ex6sWL?-?7TJU)L^?`~RHz?(GwU9beA=f8?Z(PIdU17Xf|GI~FmdzsU$~ zGc2#R_w$OY{(tND`^gvhMVi;hOj+*pa>eI@_rERwUlE+y*dzB{r7p>PjzaJ2MbA|) zn6ijyt~>Z-dhek-eJ?hiXnn$PDDJ3)o{Z3cei=qbFBR?DdBq7ng~|En8iO0TxSO5- z%HA`1xcB>|pv5A`4P1Y$x;ORP1ic?kk7h7G-(%&rHvgCJv5-u`-*+k=^S;?^$ikwv z-+H&NXNVkE!t+x%W+Wu^2_8Iq;@RuwKl(Z6g^zAk)}AnNeYu`(7R#xSz9}0LtD@}x zRdbnt3w*z1YkOhCFJT9xlT#js{Y{nHGJR*!`$!9KxtQ2Dkw=+|j#<>qE>75eE%B0s z^G!+l{rlJTUP=;vz-$-yZN|h$zpJj+u^V-;wk(`-`wg4fvFYo$^VV0m9P0bGvTpse z110=6Svgu99D!bGZnq{%uzi|Y{$O{fN492fli0og4V%&zHlA9w`5Ei9?@#oaw+iL? zEmDZk^x7@Ew)V;%>Ak}BT3j=AehBwSSW2IC+ObkV;QL&=xsz10I`v*#oVJ;pXLHF` z^Ze=8p>Zo~c5h44y_h{G^1o$+zGcyksZ$LYxK=Rn-Z^1eW){P7sqkb=N{$Qj+?11v z4lI>&Khpc_e;0;KSn{yq=#(AlN0+Xta!o5^n-}rW+jLgKoIl1N?)Lf4eD$odh&$uU zRmR+|GclcMRs4$;wVc*kNk3|SQR3%tH|>V%nZE~J&drTXIGVO*Z;Ml#vz*;C5%oz0 zYoZ*UD2lnQW2o`jFEQ8s$nEdLL`xaPNiWEa#w~HZo_L*r%OfUczbVzOcMLxnb|`ce~exch6sy zqh%?e`?T-o<=$Hp(-Rm%jjya|OHpuZ39DMWtigaLU(4&eEDQEL_qn0TZ!w!$ zb*;f7^P};zH)a17lH3O&TavVPt&GM zzAPCv!Ad&tt8hSHRb^k0>YUQ$WvP5;*7YQMOkUFPO5jv`!)?R7e~CR720Z7OCD<-C z)U>XD$kpXsu=W16Cz8gxw^z+LWc9ek)OSg=!F6HgbRzD8v$yi9!lp^GE4FADo<05AVvSizO}W+<1=GXw%PrsW z{+qx5xBPXEX#vX_JD+^`3&PGNiT?x(ij z=jaLidL&-i7_4s_5aZWe9F=-oKy1yGdl&PLPmI|ox~rr~$^4#Z_O4UnA6cIr`*~{i zlo@8(7aoOd2%FW-{2(f?JjH9p&9_x~SYc4fY--?Q>`#xGE-q~g)XJMsJiSSzUQ3saF`%(GcwOAys;8%>n$CD0zJ6at;Zv^THNP}7|9NEC+1dU1puCD{ z*Dke2A@gFtKz{pA99akdOuldb^-6H@cK0OnVDDN{af9QbyEjJf;as}Y_M3|AnY&JZ z`scqo-L_xuw?WaDqB-tIw-=iAU;bBB`*-5{)vGLbeg2d@rz&=j4>DKQkL`nU>`j&i&TBHdsuat*ahwL z_Mg7GJ8kSctz7tbXYi@WFON;%@#MMu6l6Oz&95Tm$j_{M?=>IGc`#U1C{Fok`%O_L zWZiBCxwUCUHVagk%;RcbuF4BycrqjLW4K@cQKyv`4p$yO zaxnY9Lc=W~PPx^|HfnMj2RIW>tUu2CL62u5!>Ok=QI2m;-8Ot-Ys$3o(YMR!03yu={(} zp?b+HJ8td#TUj>q(wUeyy7m9g7%QruTlp;LO~J7pPiJhI)%fJB@7J#AX`50GL@k=} z|BABfqwYOVSKa0;-_0g#{qtS!cJ(Rh#ut~oIyB>>*0=nnQ-Mi28e?Qfq|Nl+8{eAA_>6P9E zmQRoDJvgQI=jr%=S+Bm`JYRRMH#+LW>G+qoZ^+5lKkc9Y^G*7$$?x)}hOgS-_xXw1 z`HQ(fU+n+?dw-#jMf~4;8?)FK#r~*$_ovX*`D10KbkuhX=|3ASGSA30y0Bdc5&u2= z{-3m{Un~7Jh5`F<{8F8??CzTPFfpDX?Omc1{0B$Q$K>&=_s`F~PY zd^!IAzWo1Bi|aEzs^?ih7j*eOZ%_ApwZMZX=PdY|!scn_7vR*o_5Q4N8oZJ5pY(kf zO`oYRVQ<8mb_LgOz-7YHq5j(TY_-+H^-VN*= zUPndz+t1jgbT0|?Sux>x(v|tf37WQlSUwvt^<8{*exm4B-%O?N9}E@+YHbtT^j|Da z4MN^*nvi#ku zru3*|^Xc+?bfmBR9SJsbf(;ez3F67oY67zlb{hBWuJlqWzoUnes z!+AqN`r4N}=fntqI-NehR!_f9?eXo03r|YVV)J)Cf4}B)?+mu-$tP|YnqON`{%p=P z7rWS=mw8jNo=#d+R`>7N>-ERW{OWtAK00|vYI(PO^_%F^tlRl2efljkVuaex6kjs( zI8nIXZEmrYO=;4$}5`Kc3#|R z_UqEs>2f=Set*B!bUR=d(~p2txyB)@r6sOkPWW+bi>$PMlGGgQIrl$I>#sFx+XFh2N}M8;Ck0JbfZe6X1f%dmGLsYTfOrOx0jtQONtXee5^)u z*&6@4=O-<`eLVg->ePFipD7VbY|j__Nk48|(cR5Hzv|WT8^NNw-)DYjNM@3;I$GlQ zIqulcPjCM6ugi^b-k9ij=Il3d>3luEb)Ka;>nmT*$vl2+$B)fT;`wsFzir?Duf8C$ zc)FA2!3R1Ms&*^)WPXVM?BUy)zIM{gS&HpaEsCX!orBDKst@;OrkzQ6DDd)->?(bw ziAy;B>yA%7`_x-;;uUpt23(ec1$M&7=w(&;WbI-Q< zs}xyurZUv86u0SDH)T=3AN@CQ`t;ISzWUGS{4|WQe*4Vk-O5hx)*D7oulhWnZvX%0 z`Oh_mljx0B3&$sV3{dj!e*R@eGKjQ8ceO;O%^lryzKaKSbz2A(? zcL_e-leN!p!5v>!Tlu-?Wy|mQP2c{W!a!oI)1FZ6B}_;8xP{>S0-M|;AbRMr*0D69LnI{qJ5`qcAT zUoP|tC-ZsivHUF~WB6!CigSm}|M&lYt#8iU(DG$Y+j91QzrX*N4Yz)-@Jixj;B9gJ zu4O_D$>%RWz7YTam-+o4xAP4;Z_fSuxxY@tII*g&{Oz$N=Fg9%r)TQ4op?Kg=lHh+ zo^i^Y$;o_wdh`GI^0l1b_|)D0*L445I^{>^3P0HYbM~Fy_4Ple%h!IIJin`Z(f?2S z_Ok+)Ci`4(N=)vYcqJq^Dw;3eX8nuoI^GFNe*?nSh_~4W3hY?@EYv4Gt$o>zUl+J$ z?%;0*>i0>>nPGE7)#Qu*%A* z>yEZ~P{$g1ZJUCXLJU)$mneAnS6c61{nGkOeuHzW+58fpJy%UE&ao-SZuN0IF8O74 za7=N{u9*`SM{N<9tgtKn+>x!RPt0t6t{WYE5Gecph}pdbHij8R4_55kw#GAD!^*xp zv*3=jPq(B+y20^jE9|8A>@4Vdb)e->JN+W|GM_D^`@Z)_YC$ET;kG(ynZL`ZpsNiGv9H(b9VQ+`xVN|c9)B0 zMYtW7ue1-kBWIJo!Bm2)_{{n1v;9tL|GYkjP5b*x0X6Tndl){hpKm8E)9xaF;9AT2 z<8p_24_p$Q;PhotaHph`o&3>{{cIUKL)UCQog8=YX2Pi_q6|;;^q+LAnCzdcx;*6K z!Jl)NA3SE>a;WC^T1{7{+~qdMbwo?+6N%j;?d zq6%A8)auNSeVtaRSH5uCY4Ny@`LeM^$WS3*_xUg3u{Rr6iO2n@FMhOl=2CGf^H+hry?HX5a_8tt?z_10 z`n~zuzJ{%RldCO{9-WYKNT79j?opRt%+v1fSZkgnB^|jv>2kOJ9)WDJvK2c02}iY# z9X;A=RG=0iv&lwj^<7b=`E2(d-Ab8i&-9Xw*;7?xY1@Q7MGxP6l2Vkt(0jLl+2*44 zA_mQ`k?U6cIjR3Br@*HwRHLxa<=*KD;%yh?JtYk7`+XR1W+iGqxmS>U=aPKqe-GAq zC*$VG9A?pW+sDFt>@rJ8PSE1h3hgsK8Xa!!`h0qNa&k=dqbt2DKmFR$B%|(!SXL#e9!)Hbm~ZDDk{;af98oU71}ouT%%y`Hcp zO>R>Sah_>9OU#M!%jMho`$Io}lh9svaD&u2seLEIUa{NHNN-M-)6Nf`6@9S$lhwZ4 zS2l(n;&ruPUngnmyZhs@+5bPv7puh_>{7m0`MkW+?8hG&;d3%7ix$k>(EI1^`?~Vi zYquM12(WDL*_~^7y>yjS|Bd(d|BJtO=*XV&EPb(T_R9-w^Zp(^YyNk`@*P?S{{M{s z|MlkiTC*jEMm%@({w=RxHPc|3S6ptG`kG8%|EZ@A7K(nk|M%|wsVin=eUf^4&baiM z!DplQyyt$dy}oIBiuAf?HxnFuc=OYnY-~V&={-4LH-~a2Bd%VPI z&5!BzKc`!$`(zrjKVykVJGAY_bNBzB7VqEjQ{V2_#r+}2Ig*s_NM5`+JEL1l!Lqp^ zG@AGG2XTj&+K!v6*J$W)eE+xQ;}!3-;wHj-xjrbf*;SlhxH@97Z{~`iLpnjLR|iVe zAM;yNrLoG~NafENhl+Q8Hc?&64@eZ2s4p)u7g{>8NUnKH*^E_J=SatHd(!B)>hzn+ zV~zV?%2v(%GNXM~0jI$~(f$*c_8vU-TSjT$LgmN#)k%h3uP*66Q}=7BjS{#oSf6($ z$Y8Hm$+hkl=WD07o9_1Bli4|$mGg56&t?vXBZUe1`deSL7o8|tB2jg9Sy9{E2#&or z-IgB~e_ZjR;;4PUos@r9pX=E#d@H8$%hM_EZQ88FvckKZf`$& z#XL%WU&ZPfNnTY&?G(RqCR z(aT#tbp0%tE2&qhdaL+B_RRJTej9zRFI{RF`$Qt~@9+0}j~nYsKRC{|?WmNIpMw3* zC&87Prjt4UAKKs-vVGH%qFW9t9@X!XTCrZNgsokMz(*Y6v; zei@%v25$NIH(OpIz2X1n(=!@ZEOg&|uF%OZC;a81X@94l+*s~&sX|C%-}Q^~M`SE6 zGFetdh3@lDn6&5N)H#o98P-l=eg5$64T)e2L-|m{z+TUO=8X47D#{lNADr?JS>_iW zR8n(g?~%iMw}{9nRvg`5;=#V+c&#k{MMdRGh)OWer`N$ z#V)sVgMY%O)-~e7X+DQPKVTMV_)-{i^I(Etf(B=0PR{=aQF@^Ur<3i@T+m)Jz0mRZ z_2gsHuND4T-#=AL0R_X`gLP8+H$X7t#l-FTDl?+R(fR~Am&`I$uCpWaoGz^Ke| zR=Yf=pe?(r=Sg;=hF(aY@y3typC6d0^MQSnp31SF@a+0^nu=HaJvFkYdG}3xVi?$e z+HD>K9|JR+D=&Y+l-mz~aM>paM;9;_-`JsGmiH!So8wkcWM8tlp|h@Oo%zPw*B^a) z>BrI6Z8&FIwvqzRA)l4ZEep;E?(THrELO?(T~=o5af9z+5BIiX4=a`&?fsxvz!7N4 zUUr~h<;7=93m=te%dq&f+)~o~ndtdw$Ew2R8{E_xk8-{&eonIn35vA1CfNZw#MnuXN*K z<+;3w&WPMdsa-Xvjs7}oO=b58*Sz)jqPc0v*JMdHS*cSW+AWjjTky-gzxZE6a7NxM zb&Xb)O(jo+?uYx%Za&=B9sa}q zU)8_x{XLsy=h&x9E%2QbJpDrd7s0DXBp=VNd}mdAdfvY`MoW&C1u5@QU;adP?>uJZ zWjm!~4sDw#*`u&rMYfIawBy=;`wQZMVPl+)#TNr&X43&yQ20efN#`?A-okzACTz{KH(FkL}(X=KQ-n|KFG1 z{Xf}4RTf_mtG||WBv>dn?b}JCtRVIqX^$qdOLp&R-tmH-1bf-+b zb0?Sm@AbI5I~H53o;o1or%xzbMi2gAMbJuQt9$mk%BPAhL}s{{_QC zD;v#U^;0$Wam}2(t!PqbUeA$~1#MR(o-r7fn#G=t!Hpj0)pAbg%C@?=jbl1>suSf48x}&e0>}yNK zgADEF3gs=#|8YGvrbhJijn|bA62NNfQa}QnF-}|J(z)esxt}D}Q=8?NeKl{#HSvsk(OyiNsd*zRp*Z4+PI;{^a|94z- ztG2kf)NDNloe1kk>&4eU>%6&l`*iQP^Pm3QJ9$@bk3iOj+paw9W|fBL9zD`Y`eATR z?Z1H`$Zo;bJj+i&QtL#HB2kFW6i3 z^pwXh+oI{ZOC4fFZ0k>1i=FsnK6#4YhS#6|ESCRz0$eaU4Kuf zH*-GfSkQE1ZH%PT9AqTzqIEc|=%6zWP|O`k6oP z{uQwEYI|^1z74gTqr_e%dVWSj=IujM)Z2gFNEh1Zm9($cR=@7qW8I>fYdb3B)0-a) zgsn1N_-M8HgE+5CoJ()$>%TlzJ;le^KrcV$5Wo420RE-F#Fuy9zjH_1yZwcU{*+_3 z!R0GkELLiKKD+(L3PJZNqO(p+>*7AIn-$RhY4?xW!Q55<{;b{p_}+sZOnT*~^0dyg zg)3jEHA+2l@`n7M2knOJeLGiLS+kW}$j*(P$6NO1Z1ojp@n3U`PULRC$5xmA=iI$c z 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

38Vqp0H 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 |grWA2^@yV~7_#CFf>b}qYUi5X2@aONNwi>mVY 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 z

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

0inS+IM6OKn+7>eL#zo_YYo~6# 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 )j~T^ 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
^Po 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

D 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
a{e|<(%*KU9oeb`Gk6CT1Y;Kb{f6i0) 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 z≶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
  • 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

    eaL9dCf#3}&FKM^ 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�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.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj b/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj index 660cd6a7..5fe980aa 100644 --- a/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj +++ b/Samples/System/GamepadVibrationUWP/GamepadVibrationUWP.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj b/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj index d6a503ef..c763b1f8 100644 --- a/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj +++ b/Samples/System/MemoryStatisticsUWP/MemoryStatistics.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/MouseCursor/MouseCursor.vcxproj b/Samples/System/MouseCursor/MouseCursor.vcxproj index 75a94d98..80c82d0a 100644 --- a/Samples/System/MouseCursor/MouseCursor.vcxproj +++ b/Samples/System/MouseCursor/MouseCursor.vcxproj @@ -37,7 +37,6 @@ 10.0 10.0.10586.0 10.0.10586.0 - true 100 diff --git a/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj b/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj index 38309b01..893a8bf1 100644 --- a/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj +++ b/Samples/System/NLSAndLocalizationUWP/NLSAndLocalizationUWP.vcxproj @@ -41,7 +41,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj b/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj index d314cd11..ac13bd08 100644 --- a/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj +++ b/Samples/System/SimplePLM_UWP/SimplePLM.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true diff --git a/Samples/System/SystemInfoUWP/SystemInfo.vcxproj b/Samples/System/SystemInfoUWP/SystemInfo.vcxproj index 569a242c..cdf8bca6 100644 --- a/Samples/System/SystemInfoUWP/SystemInfo.vcxproj +++ b/Samples/System/SystemInfoUWP/SystemInfo.vcxproj @@ -37,7 +37,6 @@ 10.0.10586.0 10.0.10240.0 10.0 - true -- GitLab
  • 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�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 )vB#;a?Q57$I` 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

    G>?C2GSreXQbK#Fu9C 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�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