From 411a4d6f76a5661d0355973f2993770d22b44cc5 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Sun, 1 Aug 2021 23:21:32 -0700 Subject: [PATCH] DebugEffect, NormalMapEffect, PBREffect updated with instancing support (#99) --- Inc/Effects.h | 5 ++ Inc/GeometricPrimitive.h | 2 + Src/AlphaTestEffect.cpp | 16 ++-- Src/BasicEffect.cpp | 21 +++--- Src/DebugEffect.cpp | 111 +++++++++++++++++++++------ Src/DualTextureEffect.cpp | 14 ++-- Src/EffectFactory.cpp | 22 ++++-- Src/EnvironmentMapEffect.cpp | 7 +- Src/GeometricPrimitive.cpp | 15 +++- Src/NormalMapEffect.cpp | 134 ++++++++++++++++++++++++++++----- Src/PBREffect.cpp | 76 ++++++++++++++----- Src/PBREffectFactory.cpp | 25 ++++-- Src/Shaders/CompileShaders.cmd | 17 +++++ Src/Shaders/DebugEffect.fx | 74 ++++++++++++++++++ Src/Shaders/NormalMapEffect.fx | 108 ++++++++++++++++++++++++++ Src/Shaders/PBREffect.fx | 42 +++++++++++ Src/Shaders/Structures.fxh | 17 +++++ Src/Shaders/Utilities.fxh | 19 +++++ Src/SkinnedEffect.cpp | 17 +++-- 19 files changed, 640 insertions(+), 102 deletions(-) diff --git a/Inc/Effects.h b/Inc/Effects.h index 05c7c97..d9ad5ce 100644 --- a/Inc/Effects.h +++ b/Inc/Effects.h @@ -154,6 +154,7 @@ namespace DirectX constexpr uint32_t PerPixelLighting = 0x04 | Lighting; // per pixel lighting implies lighting enabled constexpr uint32_t VertexColor = 0x08; constexpr uint32_t Texture = 0x10; + constexpr uint32_t Instancing = 0x20; constexpr uint32_t Specular = 0x100; // enable optional specular/specularMap feature constexpr uint32_t Emissive = 0x200; // enable optional emissive/emissiveMap feature @@ -799,6 +800,8 @@ namespace DirectX void __cdecl EnableFogging(bool enabled) noexcept; + void __cdecl EnableInstancing(bool enabled) noexcept; + private: // Private implementation. class Impl; @@ -838,6 +841,8 @@ namespace DirectX void __cdecl SetSharing(bool enabled) noexcept; + void __cdecl EnableInstancing(bool enabled) noexcept; + private: // Private implementation. class Impl; diff --git a/Inc/GeometricPrimitive.h b/Inc/GeometricPrimitive.h index 5420b27..585101f 100644 --- a/Inc/GeometricPrimitive.h +++ b/Inc/GeometricPrimitive.h @@ -78,6 +78,8 @@ namespace DirectX // Draw the primitive. void __cdecl Draw(_In_ ID3D12GraphicsCommandList* commandList) const; + void __cdecl DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation = 0) const; + private: GeometricPrimitive() noexcept(false); diff --git a/Src/AlphaTestEffect.cpp b/Src/AlphaTestEffect.cpp index 80adb9f..ef1bd96 100644 --- a/Src/AlphaTestEffect.cpp +++ b/Src/AlphaTestEffect.cpp @@ -62,7 +62,7 @@ public: D3D12_GPU_DESCRIPTOR_HANDLE texture; D3D12_GPU_DESCRIPTOR_HANDLE textureSampler; - int GetPipelineStatePermutation(bool vertexColorEnabled) const noexcept; + int GetPipelineStatePermutation(uint32_t effectFlags) const noexcept; void Apply(_In_ ID3D12GraphicsCommandList* commandList); }; @@ -219,13 +219,17 @@ AlphaTestEffect::Impl::Impl( } else if (effectFlags & EffectFlags::Lighting) { - DebugTrace("ERROR: DualTextureEffect does not implement EffectFlags::Lighting\n"); + DebugTrace("ERROR: AlphaTestEffect does not implement EffectFlags::Lighting\n"); throw std::invalid_argument("Lighting effect flag is invalid"); } + else if (effectFlags & EffectFlags::Instancing) + { + DebugTrace("ERROR: AlphaTestEffect does not implement EffectFlags::Instancing\n"); + throw std::invalid_argument("Instancing effect flag is invalid"); + } // Create pipeline state. - int sp = GetPipelineStatePermutation( - (effectFlags & EffectFlags::VertexColor) != 0); + int sp = GetPipelineStatePermutation(effectFlags); assert(sp >= 0 && sp < AlphaTestEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < AlphaTestEffectTraits::ShaderPermutationCount); @@ -247,7 +251,7 @@ AlphaTestEffect::Impl::Impl( } -int AlphaTestEffect::Impl::GetPipelineStatePermutation(bool vertexColorEnabled) const noexcept +int AlphaTestEffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noexcept { int permutation = 0; @@ -258,7 +262,7 @@ int AlphaTestEffect::Impl::GetPipelineStatePermutation(bool vertexColorEnabled) } // Support vertex coloring? - if (vertexColorEnabled) + if (effectFlags & EffectFlags::VertexColor) { permutation += 2; } diff --git a/Src/BasicEffect.cpp b/Src/BasicEffect.cpp index 9b2ce3f..e9765e9 100644 --- a/Src/BasicEffect.cpp +++ b/Src/BasicEffect.cpp @@ -72,7 +72,7 @@ public: EffectLights lights; - int GetPipelineStatePermutation(bool preferPerPixelLighting, bool vertexColorEnabled, bool biasedVertexNormals) const noexcept; + int GetPipelineStatePermutation(uint32_t effectFlags) const noexcept; void Apply(_In_ ID3D12GraphicsCommandList* commandList); }; @@ -423,6 +423,12 @@ BasicEffect::Impl::Impl( static_assert(static_cast(std::size(EffectBase::PixelShaderBytecode)) == BasicEffectTraits::PixelShaderCount, "array/max mismatch"); static_assert(static_cast(std::size(EffectBase::PixelShaderIndices)) == BasicEffectTraits::ShaderPermutationCount, "array/max mismatch"); + if (effectFlags & EffectFlags::Instancing) + { + DebugTrace("ERROR: BasicEffect does not implement EffectFlags::Instancing\n"); + throw std::invalid_argument("Instancing effect flag is invalid"); + } + lights.InitializeConstants(constants.specularColorAndPower, constants.lightDirection, constants.lightDiffuseColor, constants.lightSpecularColor); fog.enabled = (effectFlags & EffectFlags::Fog) != 0; @@ -470,10 +476,7 @@ BasicEffect::Impl::Impl( assert(mRootSignature != nullptr); // Create pipeline state. - int sp = GetPipelineStatePermutation( - (effectFlags & EffectFlags::PerPixelLightingBit) != 0, - (effectFlags & EffectFlags::VertexColor) != 0, - (effectFlags & EffectFlags::BiasedVertexNormals) != 0); + int sp = GetPipelineStatePermutation(effectFlags); assert(sp >= 0 && sp < BasicEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < BasicEffectTraits::ShaderPermutationCount); @@ -495,7 +498,7 @@ BasicEffect::Impl::Impl( } -int BasicEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting, bool vertexColorEnabled, bool biasedVertexNormals) const noexcept +int BasicEffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noexcept { int permutation = 0; @@ -506,7 +509,7 @@ int BasicEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting, } // Support vertex coloring? - if (vertexColorEnabled) + if (effectFlags & EffectFlags::VertexColor) { permutation += 2; } @@ -519,7 +522,7 @@ int BasicEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting, if (lightingEnabled) { - if (preferPerPixelLighting) + if (effectFlags & EffectFlags::PerPixelLightingBit) { // Do lighting in the pixel shader. permutation += 16; @@ -529,7 +532,7 @@ int BasicEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting, permutation += 8; } - if (biasedVertexNormals) + if (effectFlags & EffectFlags::BiasedVertexNormals) { // Compressed normals need to be scaled and biased in the vertex shader. permutation += 16; diff --git a/Src/DebugEffect.cpp b/Src/DebugEffect.cpp index dce8edf..90578d0 100644 --- a/Src/DebugEffect.cpp +++ b/Src/DebugEffect.cpp @@ -33,9 +33,9 @@ namespace { using ConstantBufferType = DebugEffectConstants; - static constexpr int VertexShaderCount = 4; + static constexpr int VertexShaderCount = 8; static constexpr int PixelShaderCount = 4; - static constexpr int ShaderPermutationCount = 16; + static constexpr int ShaderPermutationCount = 32; static constexpr int RootSignatureCount = 1; }; } @@ -53,7 +53,7 @@ public: RootParameterCount }; - int GetPipelineStatePermutation(bool vertexColorEnabled, DebugEffect::Mode debugMode, bool biasedVertexNormals) const noexcept; + int GetPipelineStatePermutation(DebugEffect::Mode debugMode, uint32_t effectFlags) const noexcept; void Apply(_In_ ID3D12GraphicsCommandList* commandList); }; @@ -64,10 +64,16 @@ namespace { #ifdef _GAMING_XBOX_SCARLETT #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebug.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugVc.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugVcInst.inc" #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugBn.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugBnInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugVcBn.inc" + #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_VSDebugVcBnInst.inc" #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_PSHemiAmbient.inc" #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_PSRGBNormals.inc" @@ -75,10 +81,16 @@ namespace #include "Shaders/Compiled/XboxGamingScarlettDebugEffect_PSRGBBiTangents.inc" #elif defined(_GAMING_XBOX) #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebug.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugVc.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugVcInst.inc" #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugBn.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugBnInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugVcBn.inc" + #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_VSDebugVcBnInst.inc" #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_PSHemiAmbient.inc" #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_PSRGBNormals.inc" @@ -86,10 +98,16 @@ namespace #include "Shaders/Compiled/XboxGamingXboxOneDebugEffect_PSRGBBiTangents.inc" #elif defined(_XBOX_ONE) && defined(_TITLE) #include "Shaders/Compiled/XboxOneDebugEffect_VSDebug.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugInst.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugVc.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugVcInst.inc" #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugBn.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugBnInst.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugVcBn.inc" + #include "Shaders/Compiled/XboxOneDebugEffect_VSDebugVcBnInst.inc" #include "Shaders/Compiled/XboxOneDebugEffect_PSHemiAmbient.inc" #include "Shaders/Compiled/XboxOneDebugEffect_PSRGBNormals.inc" @@ -97,10 +115,16 @@ namespace #include "Shaders/Compiled/XboxOneDebugEffect_PSRGBBiTangents.inc" #else #include "Shaders/Compiled/DebugEffect_VSDebug.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugInst.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugVc.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugVcInst.inc" #include "Shaders/Compiled/DebugEffect_VSDebugBn.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugBnInst.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugVcBn.inc" + #include "Shaders/Compiled/DebugEffect_VSDebugVcBnInst.inc" #include "Shaders/Compiled/DebugEffect_PSHemiAmbient.inc" #include "Shaders/Compiled/DebugEffect_PSRGBNormals.inc" @@ -113,17 +137,20 @@ namespace template<> const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = { - { DebugEffect_VSDebug, sizeof(DebugEffect_VSDebug) }, - { DebugEffect_VSDebugVc, sizeof(DebugEffect_VSDebugVc) }, - - { DebugEffect_VSDebugBn, sizeof(DebugEffect_VSDebugBn) }, - { DebugEffect_VSDebugVcBn, sizeof(DebugEffect_VSDebugVcBn) }, + { DebugEffect_VSDebug, sizeof(DebugEffect_VSDebug) }, + { DebugEffect_VSDebugVc, sizeof(DebugEffect_VSDebugVc) }, + { DebugEffect_VSDebugBn, sizeof(DebugEffect_VSDebugBn) }, + { DebugEffect_VSDebugVcBn, sizeof(DebugEffect_VSDebugVcBn) }, + { DebugEffect_VSDebugInst, sizeof(DebugEffect_VSDebugInst) }, + { DebugEffect_VSDebugVcInst, sizeof(DebugEffect_VSDebugVcInst) }, + { DebugEffect_VSDebugBnInst, sizeof(DebugEffect_VSDebugBnInst) }, + { DebugEffect_VSDebugVcBnInst, sizeof(DebugEffect_VSDebugVcBnInst) }, }; template<> const int EffectBase::VertexShaderIndices[] = -{ +{ 0, // default 0, // normals 0, // tangents @@ -143,22 +170,41 @@ const int EffectBase::VertexShaderIndices[] = 3, // vertex color (biased vertex normal) + normals 3, // vertex color (biased vertex normal) + tangents 3, // vertex color (biased vertex normal) + bitangents -}; + 4, // instancing + 4, // instancing + normals + 4, // instancing + tangents + 4, // instancing + bitangents + + 5, // instancing + vertex color + default + 5, // instancing + vertex color + normals + 5, // instancing + vertex color + tangents + 5, // instancing + vertex color + bitangents + + 6, // instancing (biased vertex normal) + 6, // instancing + normals (biased vertex normal) + 6, // instancing + tangents (biased vertex normal) + 6, // instancing + bitangents (biased vertex normal) + + 7, // instancing + vertex color (biased vertex normal) + 7, // instancing + vertex color (biased vertex normal) + normals + 7, // instancing + vertex color (biased vertex normal) + tangents + 7, // instancing + vertex color (biased vertex normal) + bitangents}; +}; template<> const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = { - { DebugEffect_PSHemiAmbient, sizeof(DebugEffect_PSHemiAmbient) }, - { DebugEffect_PSRGBNormals, sizeof(DebugEffect_PSRGBNormals) }, - { DebugEffect_PSRGBTangents, sizeof(DebugEffect_PSRGBTangents) }, + { DebugEffect_PSHemiAmbient, sizeof(DebugEffect_PSHemiAmbient) }, + { DebugEffect_PSRGBNormals, sizeof(DebugEffect_PSRGBNormals) }, + { DebugEffect_PSRGBTangents, sizeof(DebugEffect_PSRGBTangents) }, { DebugEffect_PSRGBBiTangents, sizeof(DebugEffect_PSRGBBiTangents) }, }; template<> const int EffectBase::PixelShaderIndices[] = -{ +{ 0, // default 1, // normals 2, // tangents @@ -178,6 +224,26 @@ const int EffectBase::PixelShaderIndices[] = 1, // vertex color (biased vertex normal) + normals 2, // vertex color (biased vertex normal) + tangents 3, // vertex color (biased vertex normal) + bitangents + + 0, // instancing + 1, // instancing + normals + 2, // instancing + tangents + 3, // instancing + bitangents + + 0, // instancing + vertex color + default + 1, // instancing + vertex color + normals + 2, // instancing + vertex color + tangents + 3, // instancing + vertex color + bitangents + + 0, // instancing (biased vertex normal) + 1, // instancing + normals (biased vertex normal) + 2, // instancing + tangents (biased vertex normal) + 3, // instancing + bitangents (biased vertex normal) + + 0, // instancing + vertex color (biased vertex normal) + 1, // instancing + vertex color (biased vertex normal) + normals + 2, // instancing + vertex color (biased vertex normal) + tangents + 3, // instancing + vertex color (biased vertex normal) + bitangents }; @@ -227,10 +293,7 @@ DebugEffect::Impl::Impl( assert(mRootSignature != nullptr); // Create pipeline state. - int sp = GetPipelineStatePermutation( - (effectFlags & EffectFlags::VertexColor) != 0, - debugMode, - (effectFlags & EffectFlags::BiasedVertexNormals) != 0); + int sp = GetPipelineStatePermutation(debugMode, effectFlags); assert(sp >= 0 && sp < DebugEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < DebugEffectTraits::ShaderPermutationCount); @@ -252,22 +315,28 @@ DebugEffect::Impl::Impl( } -int DebugEffect::Impl::GetPipelineStatePermutation(bool vertexColorEnabled, DebugEffect::Mode debugMode, bool biasedVertexNormals) const noexcept +int DebugEffect::Impl::GetPipelineStatePermutation(DebugEffect::Mode debugMode, uint32_t effectFlags) const noexcept { int permutation = static_cast(debugMode); // Support vertex coloring? - if (vertexColorEnabled) + if (effectFlags & EffectFlags::VertexColor) { permutation += 4; } - if (biasedVertexNormals) + if (effectFlags & EffectFlags::BiasedVertexNormals) { // Compressed normals need to be scaled and biased in the vertex shader. permutation += 8; } + if (effectFlags & EffectFlags::Instancing) + { + // Vertex shader needs to use vertex matrix transform. + permutation += 16; + } + return permutation; } diff --git a/Src/DualTextureEffect.cpp b/Src/DualTextureEffect.cpp index fdfd176..5d70763 100644 --- a/Src/DualTextureEffect.cpp +++ b/Src/DualTextureEffect.cpp @@ -62,7 +62,7 @@ public: D3D12_GPU_DESCRIPTOR_HANDLE texture2; D3D12_GPU_DESCRIPTOR_HANDLE texture2Sampler; - int GetPipelineStatePermutation(bool vertexColorEnabled) const noexcept; + int GetPipelineStatePermutation(uint32_t effectFlags) const noexcept; void Apply(_In_ ID3D12GraphicsCommandList* commandList); }; @@ -213,10 +213,14 @@ DualTextureEffect::Impl::Impl( DebugTrace("ERROR: DualTextureEffect does not implement EffectFlags::Lighting\n"); throw std::invalid_argument("Lighting effect flag is invalid"); } + else if (effectFlags & EffectFlags::Instancing) + { + DebugTrace("ERROR: DualTextureEffect does not implement EffectFlags::Instancing\n"); + throw std::invalid_argument("Instancing effect flag is invalid"); + } // Create pipeline state. - int sp = GetPipelineStatePermutation( - (effectFlags & EffectFlags::VertexColor) != 0); + int sp = GetPipelineStatePermutation(effectFlags); assert(sp >= 0 && sp < DualTextureEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < DualTextureEffectTraits::ShaderPermutationCount); @@ -238,7 +242,7 @@ DualTextureEffect::Impl::Impl( } -int DualTextureEffect::Impl::GetPipelineStatePermutation(bool vertexColorEnabled) const noexcept +int DualTextureEffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noexcept { int permutation = 0; @@ -249,7 +253,7 @@ int DualTextureEffect::Impl::GetPipelineStatePermutation(bool vertexColorEnabled } // Support vertex coloring? - if (vertexColorEnabled) + if (effectFlags & EffectFlags::VertexColor) { permutation += 2; } diff --git a/Src/EffectFactory.cpp b/Src/EffectFactory.cpp index b0ed3fd..f72629f 100644 --- a/Src/EffectFactory.cpp +++ b/Src/EffectFactory.cpp @@ -28,12 +28,13 @@ public: Impl(_In_ ID3D12Device* device, _In_ ID3D12DescriptorHeap* textureDescriptors, _In_ ID3D12DescriptorHeap* samplerDescriptors) noexcept(false) : mTextureDescriptors(nullptr) , mSamplerDescriptors(nullptr) + , mSharing(true) , mUseNormalMapEffect(true) , mEnablePerPixelLighting(true) , mEnableFog(false) + , mEnableInstancing(false) , mDevice(device) - , mSharing(true) - { + { if (textureDescriptors) mTextureDescriptors = std::make_unique(textureDescriptors); if (samplerDescriptors) @@ -49,14 +50,15 @@ public: int samplerDescriptorOffset); void ReleaseCache(); - void SetSharing(bool enabled) noexcept { mSharing = enabled; } std::unique_ptr mTextureDescriptors; std::unique_ptr mSamplerDescriptors; + bool mSharing; bool mUseNormalMapEffect; bool mEnablePerPixelLighting; bool mEnableFog; + bool mEnableInstancing; private: ComPtr mDevice; @@ -68,8 +70,6 @@ private: EffectCache mEffectCacheDualTexture; EffectCache mEffectCacheNormalMap; - bool mSharing; - std::mutex mutex; }; @@ -280,6 +280,11 @@ std::shared_ptr EffectFactory::Impl::CreateEffect( effectflags |= EffectFlags::Fog; } + if (mEnableInstancing) + { + effectflags |= EffectFlags::Instancing; + } + if (info.perVertexColor) { effectflags |= EffectFlags::VertexColor; @@ -532,7 +537,7 @@ void EffectFactory::ReleaseCache() void EffectFactory::SetSharing(bool enabled) noexcept { - pImpl->SetSharing(enabled); + pImpl->mSharing = enabled; } void EffectFactory::EnablePerPixelLighting(bool enabled) noexcept @@ -545,6 +550,11 @@ void EffectFactory::EnableFogging(bool enabled) noexcept pImpl->mEnableFog = enabled; } +void EffectFactory::EnableInstancing(bool enabled) noexcept +{ + pImpl->mEnableInstancing = enabled; +} + void EffectFactory::EnableNormalMapEffect(bool enabled) noexcept { pImpl->mUseNormalMapEffect = enabled; diff --git a/Src/EnvironmentMapEffect.cpp b/Src/EnvironmentMapEffect.cpp index a1bd9e5..05ed0c9 100644 --- a/Src/EnvironmentMapEffect.cpp +++ b/Src/EnvironmentMapEffect.cpp @@ -405,6 +405,11 @@ EnvironmentMapEffect::Impl::Impl( DebugTrace("ERROR: EnvironmentMapEffect does not implement EffectFlags::VertexColor\n"); throw std::invalid_argument("VertexColor effect flag is invalid"); } + else if (effectFlags & EffectFlags::Instancing) + { + DebugTrace("ERROR: EnvironmentMapEffect does not implement EffectFlags::Instancing\n"); + throw std::invalid_argument("Instancing effect flag is invalid"); + } constants.environmentMapAmount = 1; constants.fresnelFactor = 1; @@ -415,9 +420,9 @@ EnvironmentMapEffect::Impl::Impl( // Create pipeline state. int sp = GetPipelineStatePermutation(mapping, effectFlags); - assert(sp >= 0 && sp < EnvironmentMapEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < EnvironmentMapEffectTraits::ShaderPermutationCount); + int vi = EffectBase::VertexShaderIndices[sp]; assert(vi >= 0 && vi < EnvironmentMapEffectTraits::VertexShaderCount); _Analysis_assume_(vi >= 0 && vi < EnvironmentMapEffectTraits::VertexShaderCount); diff --git a/Src/GeometricPrimitive.cpp b/Src/GeometricPrimitive.cpp index 02de5e1..a61cecf 100644 --- a/Src/GeometricPrimitive.cpp +++ b/Src/GeometricPrimitive.cpp @@ -40,7 +40,7 @@ public: D3D12_RESOURCE_STATES stateBeforeIB, D3D12_RESOURCE_STATES stateAfterIB); - void Draw(_In_ ID3D12GraphicsCommandList* commandList) const; + void DrawInstanced(_In_ ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation) const; UINT mIndexCount; SharedGraphicsResource mIndexBuffer; @@ -216,13 +216,13 @@ void GeometricPrimitive::Impl::Transition( // Draws the primitive. _Use_decl_annotations_ -void GeometricPrimitive::Impl::Draw(ID3D12GraphicsCommandList* commandList) const +void GeometricPrimitive::Impl::DrawInstanced(ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation) const { commandList->IASetVertexBuffers(0, 1, &mVertexBufferView); commandList->IASetIndexBuffer(&mIndexBufferView); commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - commandList->DrawIndexedInstanced(mIndexCount, 1, 0, 0, 0); + commandList->DrawIndexedInstanced(mIndexCount, instanceCount, 0, 0, startInstanceLocation); } //-------------------------------------------------------------------------------------- @@ -265,7 +265,14 @@ void GeometricPrimitive::Transition( _Use_decl_annotations_ void GeometricPrimitive::Draw(ID3D12GraphicsCommandList* commandList) const { - pImpl->Draw(commandList); + pImpl->DrawInstanced(commandList, 1, 0); +} + + +_Use_decl_annotations_ +void GeometricPrimitive::DrawInstanced(ID3D12GraphicsCommandList* commandList, uint32_t instanceCount, uint32_t startInstanceLocation) const +{ + pImpl->DrawInstanced(commandList, instanceCount, startInstanceLocation); } diff --git a/Src/NormalMapEffect.cpp b/Src/NormalMapEffect.cpp index 6d44422..e391204 100644 --- a/Src/NormalMapEffect.cpp +++ b/Src/NormalMapEffect.cpp @@ -43,9 +43,9 @@ namespace { using ConstantBufferType = NormalMapEffectConstants; - static constexpr int VertexShaderCount = 8; + static constexpr int VertexShaderCount = 16; static constexpr int PixelShaderCount = 4; - static constexpr int ShaderPermutationCount = 16; + static constexpr int ShaderPermutationCount = 32; static constexpr int RootSignatureCount = 2; }; } @@ -95,6 +95,16 @@ namespace #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxNoSpecBn.inc" #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxVcInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxNoSpecInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst.inc" + + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxBnInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxVcBnInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_PSNormalPixelLightingTx.inc" #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_PSNormalPixelLightingTxNoFog.inc" #include "Shaders/Compiled/XboxGamingScarlettNormalMapEffect_PSNormalPixelLightingTxNoSpec.inc" @@ -110,6 +120,16 @@ namespace #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecBn.inc" #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxVcInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst.inc" + + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxBnInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxVcBnInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_PSNormalPixelLightingTx.inc" #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_PSNormalPixelLightingTxNoFog.inc" #include "Shaders/Compiled/XboxGamingXboxOneNormalMapEffect_PSNormalPixelLightingTxNoSpec.inc" @@ -125,6 +145,16 @@ namespace #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecBn.inc" #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxVcInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst.inc" + + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxBnInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxVcBnInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst.inc" + #include "Shaders/Compiled/XboxOneNormalMapEffect_PSNormalPixelLightingTx.inc" #include "Shaders/Compiled/XboxOneNormalMapEffect_PSNormalPixelLightingTxNoFog.inc" #include "Shaders/Compiled/XboxOneNormalMapEffect_PSNormalPixelLightingTxNoSpec.inc" @@ -140,6 +170,16 @@ namespace #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxNoSpecBn.inc" #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxVcInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxNoSpecInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst.inc" + + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxBnInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxVcBnInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst.inc" + #include "Shaders/Compiled/NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst.inc" + #include "Shaders/Compiled/NormalMapEffect_PSNormalPixelLightingTx.inc" #include "Shaders/Compiled/NormalMapEffect_PSNormalPixelLightingTxNoFog.inc" #include "Shaders/Compiled/NormalMapEffect_PSNormalPixelLightingTxNoSpec.inc" @@ -151,17 +191,29 @@ namespace template<> const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = { - { NormalMapEffect_VSNormalPixelLightingTx, sizeof(NormalMapEffect_VSNormalPixelLightingTx) }, - { NormalMapEffect_VSNormalPixelLightingTxVc, sizeof(NormalMapEffect_VSNormalPixelLightingTxVc) }, + { NormalMapEffect_VSNormalPixelLightingTx, sizeof(NormalMapEffect_VSNormalPixelLightingTx) }, + { NormalMapEffect_VSNormalPixelLightingTxVc, sizeof(NormalMapEffect_VSNormalPixelLightingTxVc) }, - { NormalMapEffect_VSNormalPixelLightingTxBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxBn) }, - { NormalMapEffect_VSNormalPixelLightingTxVcBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcBn) }, + { NormalMapEffect_VSNormalPixelLightingTxBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxBn) }, + { NormalMapEffect_VSNormalPixelLightingTxVcBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcBn) }, - { NormalMapEffect_VSNormalPixelLightingTxNoSpec, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpec) }, - { NormalMapEffect_VSNormalPixelLightingTxVcNoSpec, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpec) }, + { NormalMapEffect_VSNormalPixelLightingTxNoSpec, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpec) }, + { NormalMapEffect_VSNormalPixelLightingTxVcNoSpec, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpec) }, - { NormalMapEffect_VSNormalPixelLightingTxNoSpecBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpecBn) }, - { NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn) }, + { NormalMapEffect_VSNormalPixelLightingTxNoSpecBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpecBn) }, + { NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBn) }, + + { NormalMapEffect_VSNormalPixelLightingTxInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxInst) }, + { NormalMapEffect_VSNormalPixelLightingTxVcInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcInst) }, + + { NormalMapEffect_VSNormalPixelLightingTxBnInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxBnInst) }, + { NormalMapEffect_VSNormalPixelLightingTxVcBnInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcBnInst) }, + + { NormalMapEffect_VSNormalPixelLightingTxNoSpecInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpecInst) }, + { NormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpecInst) }, + + { NormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxNoSpecBnInst) }, + { NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst, sizeof(NormalMapEffect_VSNormalPixelLightingTxVcNoSpecBnInst) }, }; @@ -187,6 +239,26 @@ const int EffectBase::VertexShaderIndices[] = 6, // pixel lighting (biased vertex normal) + texture, no fog or specular 7, // pixel lighting (biased vertex normal) + texture + vertex color, no specular 7, // pixel lighting (biased vertex normal) + texture + vertex color, no fog or specular + + 8, // instancing + pixel lighting + texture + 8, // instancing + pixel lighting + texture, no fog + 9, // instancing + pixel lighting + texture + vertex color + 9, // instancing + pixel lighting + texture + vertex color, no fog + + 12, // instancing + pixel lighting + texture, no specular + 12, // instancing + pixel lighting + texture, no fog or specular + 13, // instancing + pixel lighting + texture + vertex color, no specular + 13, // instancing + pixel lighting + texture + vertex color, no fog or specular + + 10, // instancing + pixel lighting (biased vertex normal) + texture + 10, // instancing + pixel lighting (biased vertex normal) + texture, no fog + 11, // instancing + pixel lighting (biased vertex normal) + texture + vertex color + 11, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no fog + + 14, // instancing + pixel lighting (biased vertex normal) + texture, no specular + 14, // instancing + pixel lighting (biased vertex normal) + texture, no fog or specular + 15, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no specular + 15, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no fog or specular }; @@ -203,25 +275,45 @@ const D3D12_SHADER_BYTECODE EffectBase::PixelShaderByteco template<> const int EffectBase::PixelShaderIndices[] = { - 0, // pixel lighting + texture - 1, // pixel lighting + texture, no fog - 0, // pixel lighting + texture + vertex color - 1, // pixel lighting + texture + vertex color, no fog + 0, // pixel lighting + texture + 1, // pixel lighting + texture, no fog + 0, // pixel lighting + texture + vertex color + 1, // pixel lighting + texture + vertex color, no fog 2, // pixel lighting + texture, no specular 3, // pixel lighting + texture, no fog or specular 2, // pixel lighting + texture + vertex color, no specular 3, // pixel lighting + texture + vertex color, no fog or specular - 0, // pixel lighting (biased vertex normal) + texture - 1, // pixel lighting (biased vertex normal) + texture, no fog - 0, // pixel lighting (biased vertex normal) + texture + vertex color - 1, // pixel lighting (biased vertex normal) + texture + vertex color, no fog + 0, // pixel lighting (biased vertex normal) + texture + 1, // pixel lighting (biased vertex normal) + texture, no fog + 0, // pixel lighting (biased vertex normal) + texture + vertex color + 1, // pixel lighting (biased vertex normal) + texture + vertex color, no fog 2, // pixel lighting (biased vertex normal) + texture, no specular 3, // pixel lighting (biased vertex normal) + texture, no fog or specular 2, // pixel lighting (biased vertex normal) + texture + vertex color, no specular 3, // pixel lighting (biased vertex normal) + texture + vertex color, no fog or specular + + 0, // instancing + pixel lighting + texture + 1, // instancing + pixel lighting + texture, no fog + 0, // instancing + pixel lighting + texture + vertex color + 1, // instancing + pixel lighting + texture + vertex color, no fog + + 2, // instancing + pixel lighting + texture, no specular + 3, // instancing + pixel lighting + texture, no fog or specular + 2, // instancing + pixel lighting + texture + vertex color, no specular + 3, // instancing + pixel lighting + texture + vertex color, no fog or specular + + 0, // instancing + pixel lighting (biased vertex normal) + texture + 1, // instancing + pixel lighting (biased vertex normal) + texture, no fog + 0, // instancing + pixel lighting (biased vertex normal) + texture + vertex color + 1, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no fog + + 2, // instancing + pixel lighting (biased vertex normal) + texture, no specular + 3, // instancing + pixel lighting (biased vertex normal) + texture, no fog or specular + 2, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no specular + 3, // instancing + pixel lighting (biased vertex normal) + texture + vertex color, no fog or specular }; // Global pool of per-device NormalMapEffect resources. @@ -340,6 +432,12 @@ int NormalMapEffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) con permutation += 8; } + if (effectFlags & EffectFlags::Instancing) + { + // Vertex shader needs to use vertex matrix transform. + permutation += 16; + } + return permutation; } diff --git a/Src/PBREffect.cpp b/Src/PBREffect.cpp index 45bb770..afb2ca5 100644 --- a/Src/PBREffect.cpp +++ b/Src/PBREffect.cpp @@ -45,9 +45,9 @@ namespace { using ConstantBufferType = PBREffectConstants; - static constexpr int VertexShaderCount = 4; + static constexpr int VertexShaderCount = 6; static constexpr int PixelShaderCount = 5; - static constexpr int ShaderPermutationCount = 10; + static constexpr int ShaderPermutationCount = 16; static constexpr int RootSignatureCount = 1; }; } @@ -92,8 +92,12 @@ namespace { #ifdef _GAMING_XBOX_SCARLETT #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstant.inc" - #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantBn.inc" + + #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantInst.inc" + #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantBnInst.inc" + + #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxGamingScarlettPBREffect_VSConstantVelocityBn.inc" #include "Shaders/Compiled/XboxGamingScarlettPBREffect_PSConstant.inc" @@ -103,8 +107,12 @@ namespace #include "Shaders/Compiled/XboxGamingScarlettPBREffect_PSTexturedEmissiveVelocity.inc" #elif defined(_GAMING_XBOX) #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstant.inc" - #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantBn.inc" + + #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantInst.inc" + #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantBnInst.inc" + + #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_VSConstantVelocityBn.inc" #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_PSConstant.inc" @@ -114,8 +122,12 @@ namespace #include "Shaders/Compiled/XboxGamingXboxOnePBREffect_PSTexturedEmissiveVelocity.inc" #elif defined(_XBOX_ONE) && defined(_TITLE) #include "Shaders/Compiled/XboxOnePBREffect_VSConstant.inc" - #include "Shaders/Compiled/XboxOnePBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxOnePBREffect_VSConstantBn.inc" + + #include "Shaders/Compiled/XboxOnePBREffect_VSConstantInst.inc" + #include "Shaders/Compiled/XboxOnePBREffect_VSConstantBnInst.inc" + + #include "Shaders/Compiled/XboxOnePBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/XboxOnePBREffect_VSConstantVelocityBn.inc" #include "Shaders/Compiled/XboxOnePBREffect_PSConstant.inc" @@ -125,8 +137,12 @@ namespace #include "Shaders/Compiled/XboxOnePBREffect_PSTexturedEmissiveVelocity.inc" #else #include "Shaders/Compiled/PBREffect_VSConstant.inc" - #include "Shaders/Compiled/PBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/PBREffect_VSConstantBn.inc" + + #include "Shaders/Compiled/PBREffect_VSConstantInst.inc" + #include "Shaders/Compiled/PBREffect_VSConstantBnInst.inc" + + #include "Shaders/Compiled/PBREffect_VSConstantVelocity.inc" #include "Shaders/Compiled/PBREffect_VSConstantVelocityBn.inc" #include "Shaders/Compiled/PBREffect_PSConstant.inc" @@ -141,10 +157,12 @@ namespace template<> const D3D12_SHADER_BYTECODE EffectBase::VertexShaderBytecode[] = { - { PBREffect_VSConstant, sizeof(PBREffect_VSConstant) }, - { PBREffect_VSConstantVelocity, sizeof(PBREffect_VSConstantVelocity) }, - { PBREffect_VSConstantBn, sizeof(PBREffect_VSConstantBn) }, + { PBREffect_VSConstant, sizeof(PBREffect_VSConstant) }, + { PBREffect_VSConstantVelocity, sizeof(PBREffect_VSConstantVelocity) }, + { PBREffect_VSConstantBn, sizeof(PBREffect_VSConstantBn) }, { PBREffect_VSConstantVelocityBn, sizeof(PBREffect_VSConstantVelocityBn) }, + { PBREffect_VSConstantInst, sizeof(PBREffect_VSConstantInst) }, + { PBREffect_VSConstantBnInst, sizeof(PBREffect_VSConstantBnInst) }, }; @@ -156,23 +174,29 @@ const int EffectBase::VertexShaderIndices[] = 0, // textured + emissive 1, // textured + velocity 1, // textured + emissive + velocity + 4, // instancing + constant + 4, // instancing + textured + 4, // instancing + textured + emissive 2, // constant (biased vertex normals) 2, // textured (biased vertex normals) 2, // textured + emissive (biased vertex normals) 3, // textured + velocity (biased vertex normals) 3, // textured + emissive + velocity (biasoed vertex normals) + 5, // instancing + constant (biased vertex normals) + 5, // instancing + textured (biased vertex normals) + 5, // instancing + textured + emissive (biased vertex normals) }; template<> const D3D12_SHADER_BYTECODE EffectBase::PixelShaderBytecode[] = { - { PBREffect_PSConstant, sizeof(PBREffect_PSConstant) }, - { PBREffect_PSTextured, sizeof(PBREffect_PSTextured) }, - { PBREffect_PSTexturedEmissive, sizeof(PBREffect_PSTexturedEmissive) }, - { PBREffect_PSTexturedVelocity, sizeof(PBREffect_PSTexturedVelocity) }, - { PBREffect_PSTexturedEmissiveVelocity, sizeof(PBREffect_PSTexturedEmissiveVelocity) } + { PBREffect_PSConstant, sizeof(PBREffect_PSConstant) }, + { PBREffect_PSTextured, sizeof(PBREffect_PSTextured) }, + { PBREffect_PSTexturedEmissive, sizeof(PBREffect_PSTexturedEmissive) }, + { PBREffect_PSTexturedVelocity, sizeof(PBREffect_PSTexturedVelocity) }, + { PBREffect_PSTexturedEmissiveVelocity, sizeof(PBREffect_PSTexturedEmissiveVelocity) }, }; @@ -184,12 +208,18 @@ const int EffectBase::PixelShaderIndices[] = 2, // textured + emissive 3, // textured + velocity 4, // textured + emissive + velocity + 0, // instancing + constant + 1, // instancing + textured + 2, // instancing + textured + emissive 0, // constant (biased vertex normals) 1, // textured (biased vertex normals) 2, // textured + emissive (biased vertex normals) 3, // textured + velocity (biased vertex normals) 4, // textured + emissive + velocity (biased vertex normals) + 0, // instancing + constant (biased vertex normals) + 1, // instancing + textured (biased vertex normals) + 2, // instancing + textured + emissive (biased vertex normals) }; // Global pool of per-device PBREffect resources. Required by EffectBase<>, but not used. @@ -288,11 +318,16 @@ PBREffect::Impl::Impl(_In_ ID3D12Device* device, DebugTrace("ERROR: PBEffect does not implement EffectFlags::Fog\n"); throw std::invalid_argument("Fog effect flag is invalid"); } - else if (effectFlags & EffectFlags::VertexColor) + else if (effectFlags & EffectFlags::VertexColor) { DebugTrace("ERROR: PBEffect does not implement EffectFlags::VertexColor\n"); throw std::invalid_argument("VertexColor effect flag is invalid"); } + else if ((effectFlags & (EffectFlags::Velocity | EffectFlags::Instancing)) == (EffectFlags::Velocity | EffectFlags::Instancing)) + { + DebugTrace("ERROR: PBEffect cannot use Instancing and Velocity at the same time.\n"); + throw std::invalid_argument("Velocity effect flag is invalid"); + } // Create pipeline state. int sp = GetPipelineStatePermutation(effectFlags); @@ -321,14 +356,19 @@ int PBREffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noe { int permutation = 0; - // Textured RMA vs. constant albedo/roughness/metalness? - if (effectFlags & EffectFlags::Velocity) + if (effectFlags & EffectFlags::Instancing) + { + // Vertex shader needs to use vertex matrix transform. + permutation = (textureEnabled) ? 6 : 5; + } + else if (effectFlags & EffectFlags::Velocity) { // Optional velocity buffer (implies textured RMA)? permutation = 3; } else if (textureEnabled) { + // Textured RMA vs. constant albedo/roughness/metalness? permutation = 1; } @@ -341,7 +381,7 @@ int PBREffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noe if (effectFlags & EffectFlags::BiasedVertexNormals) { // Compressed normals need to be scaled and biased in the vertex shader. - permutation += 5; + permutation += 8; } return permutation; diff --git a/Src/PBREffectFactory.cpp b/Src/PBREffectFactory.cpp index 0160f41..1841603 100644 --- a/Src/PBREffectFactory.cpp +++ b/Src/PBREffectFactory.cpp @@ -26,11 +26,12 @@ class PBREffectFactory::Impl { public: Impl(_In_ ID3D12Device* device, _In_ ID3D12DescriptorHeap* textureDescriptors, _In_ ID3D12DescriptorHeap* samplerDescriptors) noexcept(false) - : mTextureDescriptors(nullptr) + : mSharing(true) + , mEnableInstancing(false) + , mTextureDescriptors(nullptr) , mSamplerDescriptors(nullptr) , mDevice(device) - , mSharing(true) - { + { if (textureDescriptors) mTextureDescriptors = std::make_unique(textureDescriptors); if (samplerDescriptors) @@ -46,7 +47,9 @@ public: int samplerDescriptorOffset); void ReleaseCache(); - void SetSharing(bool enabled) noexcept { mSharing = enabled; } + + bool mSharing; + bool mEnableInstancing; std::unique_ptr mTextureDescriptors; std::unique_ptr mSamplerDescriptors; @@ -58,8 +61,6 @@ private: EffectCache mEffectCache; - bool mSharing; - std::mutex mutex; }; @@ -106,6 +107,11 @@ std::shared_ptr PBREffectFactory::Impl::CreateEffect( effectflags |= EffectFlags::Emissive; } + if (mEnableInstancing) + { + effectflags |= EffectFlags::Instancing; + } + std::wstring cacheName; if (mSharing && !info.name.empty()) { @@ -231,5 +237,10 @@ void PBREffectFactory::ReleaseCache() void PBREffectFactory::SetSharing(bool enabled) noexcept { - pImpl->SetSharing(enabled); + pImpl->mSharing = enabled; +} + +void PBREffectFactory::EnableInstancing(bool enabled) noexcept +{ + pImpl->mEnableInstancing = enabled; } diff --git a/Src/Shaders/CompileShaders.cmd b/Src/Shaders/CompileShaders.cmd index eb8e8b5..1ca6241 100644 --- a/Src/Shaders/CompileShaders.cmd +++ b/Src/Shaders/CompileShaders.cmd @@ -172,14 +172,26 @@ call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxNoSpecBn call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcNoSpec call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcNoSpecBn +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxBnInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcBnInst + +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxNoSpecInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxNoSpecBnInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcNoSpecInst +call :CompileShader%1 NormalMapEffect vs VSNormalPixelLightingTxVcNoSpecBnInst + call :CompileShader%1 NormalMapEffect ps PSNormalPixelLightingTx call :CompileShader%1 NormalMapEffect ps PSNormalPixelLightingTxNoFog call :CompileShader%1 NormalMapEffect ps PSNormalPixelLightingTxNoSpec call :CompileShader%1 NormalMapEffect ps PSNormalPixelLightingTxNoFogSpec call :CompileShader%1 PBREffect vs VSConstant +call :CompileShader%1 PBREffect vs VSConstantInst call :CompileShader%1 PBREffect vs VSConstantVelocity call :CompileShader%1 PBREffect vs VSConstantBn +call :CompileShader%1 PBREffect vs VSConstantBnInst call :CompileShader%1 PBREffect vs VSConstantVelocityBn call :CompileShader%1 PBREffect ps PSConstant @@ -193,6 +205,11 @@ call :CompileShader%1 DebugEffect vs VSDebugBn call :CompileShader%1 DebugEffect vs VSDebugVc call :CompileShader%1 DebugEffect vs VSDebugVcBn +call :CompileShader%1 DebugEffect vs VSDebugInst +call :CompileShader%1 DebugEffect vs VSDebugBnInst +call :CompileShader%1 DebugEffect vs VSDebugVcInst +call :CompileShader%1 DebugEffect vs VSDebugVcBnInst + call :CompileShader%1 DebugEffect ps PSHemiAmbient call :CompileShader%1 DebugEffect ps PSRGBNormals call :CompileShader%1 DebugEffect ps PSRGBTangents diff --git a/Src/Shaders/DebugEffect.fx b/Src/Shaders/DebugEffect.fx index b7337d7..536f386 100644 --- a/Src/Shaders/DebugEffect.fx +++ b/Src/Shaders/DebugEffect.fx @@ -87,6 +87,80 @@ VSOutputPixelLightingTx VSDebugVcBn(VSInputNmTxVc vin) } +// Vertex shader: instancing +[RootSignature(DebugEffectRS)] +VSOutputPixelLightingTx VSDebugInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, vin.Normal, vin.Transform); + + vout.PositionPS = mul(inst.Position, WorldViewProj); + vout.PositionWS = float4(mul(inst.Position, World).xyz, 1); + vout.NormalWS = normalize(mul(inst.Normal, WorldInverseTranspose)); + vout.Diffuse = float4(1, 1, 1, Alpha); + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(DebugEffectRS)] +VSOutputPixelLightingTx VSDebugBnInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + float3 normal = BiasX2(vin.Normal); + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, normal, vin.Transform); + + vout.PositionPS = mul(inst.Position, WorldViewProj); + vout.PositionWS = float4(mul(inst.Position, World).xyz, 1); + vout.NormalWS = normalize(mul(inst.Normal, WorldInverseTranspose)); + vout.Diffuse = float4(1, 1, 1, Alpha); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + +// Vertex shader: vertex color + instancing +[RootSignature(DebugEffectRS)] +VSOutputPixelLightingTx VSDebugVcInst(VSInputNmTxVcInst vin) +{ + VSOutputPixelLightingTx vout; + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, vin.Normal, vin.Transform); + + vout.PositionPS = mul(inst.Position, WorldViewProj); + vout.PositionWS = float4(mul(inst.Position, World).xyz, 1); + vout.NormalWS = normalize(mul(inst.Normal, WorldInverseTranspose)); + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * Alpha; + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(DebugEffectRS)] +VSOutputPixelLightingTx VSDebugVcBnInst(VSInputNmTxVcInst vin) +{ + VSOutputPixelLightingTx vout; + + float3 normal = BiasX2(vin.Normal); + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, normal, vin.Transform); + + vout.PositionPS = mul(inst.Position, WorldViewProj); + vout.PositionWS = float4(mul(inst.Position, World).xyz, 1); + vout.NormalWS = normalize(mul(inst.Normal, WorldInverseTranspose)); + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * Alpha; + vout.TexCoord = vin.TexCoord; + + return vout; +} + + // Pixel shader: default float3 CalcHemiAmbient(float3 normal, float3 color) { diff --git a/Src/Shaders/NormalMapEffect.fx b/Src/Shaders/NormalMapEffect.fx index abbb7da..fc37d5b 100644 --- a/Src/Shaders/NormalMapEffect.fx +++ b/Src/Shaders/NormalMapEffect.fx @@ -83,6 +83,7 @@ VSOutputPixelLightingTx VSNormalPixelLightingTxNoSpecBn(VSInputNmTx vin) return VSNormalPixelLightingTxBn(vin); } + // Vertex shader: pixel lighting + texture + vertex color. [RootSignature(NormalMapRS)] VSOutputPixelLightingTx VSNormalPixelLightingTxVc(VSInputNmTxVc vin) @@ -105,6 +106,7 @@ VSOutputPixelLightingTx VSNormalPixelLightingTxVcNoSpec(VSInputNmTxVc vin) return VSNormalPixelLightingTxVc(vin); } + // Vertex shader: pixel lighting + texture + vertex color (biased normal). [RootSignature(NormalMapRS)] VSOutputPixelLightingTx VSNormalPixelLightingTxVcBn(VSInputNmTxVc vin) @@ -129,6 +131,110 @@ VSOutputPixelLightingTx VSNormalPixelLightingTxVcNoSpecBn(VSInputNmTxVc vin) return VSNormalPixelLightingTxVcBn(vin); } + +// Vertex shader: pixel lighting + texture + instancing. +[RootSignature(NormalMapRS)] +VSOutputPixelLightingTx VSNormalPixelLightingTxInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, vin.Normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(NormalMapRSNoSpec)] +VSOutputPixelLightingTx VSNormalPixelLightingTxNoSpecInst(VSInputNmTxInst vin) +{ + return VSNormalPixelLightingTxInst(vin); +} + + +// Vertex shader: pixel lighting + texture + instancing (biased normal). +[RootSignature(NormalMapRS)] +VSOutputPixelLightingTx VSNormalPixelLightingTxBnInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + float3 normal = BiasX2(vin.Normal); + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(NormalMapRSNoSpec)] +VSOutputPixelLightingTx VSNormalPixelLightingTxNoSpecBnInst(VSInputNmTxInst vin) +{ + return VSNormalPixelLightingTxBnInst(vin); +} + + +// Vertex shader: pixel lighting + texture + vertex color + instancing. +[RootSignature(NormalMapRS)] +VSOutputPixelLightingTx VSNormalPixelLightingTxVcInst(VSInputNmTxVcInst vin) +{ + VSOutputPixelLightingTx vout; + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, vin.Normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * DiffuseColor.a; + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(NormalMapRSNoSpec)] +VSOutputPixelLightingTx VSNormalPixelLightingTxVcNoSpecInst(VSInputNmTxVcInst vin) +{ + return VSNormalPixelLightingTxVcInst(vin); +} + + +// Vertex shader: pixel lighting + texture + vertex color + instancing (biased normal). +[RootSignature(NormalMapRS)] +VSOutputPixelLightingTx VSNormalPixelLightingTxVcBnInst(VSInputNmTxVcInst vin) +{ + VSOutputPixelLightingTx vout; + + float3 normal = BiasX2(vin.Normal); + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + SetCommonVSOutputParamsPixelLighting; + + vout.Diffuse.rgb = vin.Color.rgb; + vout.Diffuse.a = vin.Color.a * DiffuseColor.a; + vout.TexCoord = vin.TexCoord; + + return vout; +} + +[RootSignature(NormalMapRSNoSpec)] +VSOutputPixelLightingTx VSNormalPixelLightingTxVcNoSpecBnInst(VSInputNmTxVcInst vin) +{ + return VSNormalPixelLightingTxVcBnInst(vin); +} + + + // Pixel shader: pixel lighting + texture + no fog [RootSignature(NormalMapRS)] float4 PSNormalPixelLightingTxNoFog(PSInputPixelLightingTx pin) : SV_Target0 @@ -153,6 +259,7 @@ float4 PSNormalPixelLightingTxNoFog(PSInputPixelLightingTx pin) : SV_Target0 return color; } + // Pixel shader: pixel lighting + texture [RootSignature(NormalMapRS)] float4 PSNormalPixelLightingTx(PSInputPixelLightingTx pin) : SV_Target0 @@ -202,6 +309,7 @@ float4 PSNormalPixelLightingTxNoFogSpec(PSInputPixelLightingTx pin) : SV_Target0 return color; } + // Pixel shader: pixel lighting + texture + no specular [RootSignature(NormalMapRSNoSpec)] float4 PSNormalPixelLightingTxNoSpec(PSInputPixelLightingTx pin) : SV_Target0 diff --git a/Src/Shaders/PBREffect.fx b/Src/Shaders/PBREffect.fx index 8668f70..d4cf1e2 100644 --- a/Src/Shaders/PBREffect.fx +++ b/Src/Shaders/PBREffect.fx @@ -64,6 +64,26 @@ VSOutputPixelLightingTx VSConstant(VSInputNmTx vin) } +// Vertex shader: pbr + instancing +[RootSignature(PBREffectRS)] +VSOutputPixelLightingTx VSConstantInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, vin.Normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + + vout.PositionPS = cout.Pos_ps; + vout.PositionWS = float4(cout.Pos_ws, 1); + vout.NormalWS = cout.Normal_ws; + vout.Diffuse = float4(ConstantAlbedo, Alpha); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + // Vertex shader: pbr + velocity [RootSignature(PBREffectRS)] VSOut_Velocity VSConstantVelocity(VSInputNmTx vin) @@ -103,6 +123,28 @@ VSOutputPixelLightingTx VSConstantBn(VSInputNmTx vin) } +// Vertex shader: pbr + instancing (biased normal) +[RootSignature(PBREffectRS)] +VSOutputPixelLightingTx VSConstantBnInst(VSInputNmTxInst vin) +{ + VSOutputPixelLightingTx vout; + + float3 normal = BiasX2(vin.Normal); + + CommonInstancing inst = ComputeCommonInstancing(vin.Position, normal, vin.Transform); + + CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(inst.Position, inst.Normal); + + vout.PositionPS = cout.Pos_ps; + vout.PositionWS = float4(cout.Pos_ws, 1); + vout.NormalWS = cout.Normal_ws; + vout.Diffuse = float4(ConstantAlbedo, Alpha); + vout.TexCoord = vin.TexCoord; + + return vout; +} + + // Vertex shader: pbr + velocity (biased normal) [RootSignature(PBREffectRS)] VSOut_Velocity VSConstantVelocityBn(VSInputNmTx vin) diff --git a/Src/Shaders/Structures.fxh b/Src/Shaders/Structures.fxh index 6624d17..a2a7119 100644 --- a/Src/Shaders/Structures.fxh +++ b/Src/Shaders/Structures.fxh @@ -61,6 +61,23 @@ struct VSInputNmTxVc float4 Color : COLOR; }; +struct VSInputNmTxInst +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; + float4x3 Transform : InstMatrix; +}; + +struct VSInputNmTxVcInst +{ + float4 Position : SV_Position; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; + float4 Color : COLOR; + float4x3 Transform : InstMatrix; +}; + struct VSInputTx2 { float4 Position : SV_Position; diff --git a/Src/Shaders/Utilities.fxh b/Src/Shaders/Utilities.fxh index c4811a2..0f20aaf 100644 --- a/Src/Shaders/Utilities.fxh +++ b/Src/Shaders/Utilities.fxh @@ -102,3 +102,22 @@ float3 ToneMapACESFilmic(float3 x) float e = 0.14f; return saturate((x*(a*x+b))/(x*(c*x+d)+e)); } + + +// Instancing +struct CommonInstancing +{ + float4 Position; + float3 Normal; +}; + + +CommonInstancing ComputeCommonInstancing(float4 position, float3 normal, float4x3 itransform) +{ + CommonInstancing vout; + + vout.Position = float4(mul(position, itransform), position.w); + vout.Normal = mul(normal, (float3x3)itransform); + + return vout; +} diff --git a/Src/SkinnedEffect.cpp b/Src/SkinnedEffect.cpp index 8f1cb87..01e2d35 100644 --- a/Src/SkinnedEffect.cpp +++ b/Src/SkinnedEffect.cpp @@ -71,7 +71,7 @@ public: EffectLights lights; - int GetPipelineStatePermutation(bool preferPerPixelLighting, bool biasedVertexNormals) const noexcept; + int GetPipelineStatePermutation(uint32_t effectFlags) const noexcept; void Apply(_In_ ID3D12GraphicsCommandList* commandList); }; @@ -232,11 +232,14 @@ SkinnedEffect::Impl::Impl( DebugTrace("ERROR: SkinnedEffect does not implement EffectFlags::VertexColor\n"); throw std::invalid_argument("VertexColor effect flag is invalid"); } + else if (effectFlags & EffectFlags::Instancing) + { + DebugTrace("ERROR: SkinnedEffect does not implement EffectFlags::Instancing\n"); + throw std::invalid_argument("Instancing effect flag is invalid"); + } // Create pipeline state. - int sp = GetPipelineStatePermutation( - (effectFlags & EffectFlags::PerPixelLightingBit) != 0, - (effectFlags & EffectFlags::BiasedVertexNormals) != 0); + int sp = GetPipelineStatePermutation(effectFlags); assert(sp >= 0 && sp < SkinnedEffectTraits::ShaderPermutationCount); _Analysis_assume_(sp >= 0 && sp < SkinnedEffectTraits::ShaderPermutationCount); @@ -258,7 +261,7 @@ SkinnedEffect::Impl::Impl( } -int SkinnedEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting, bool biasedVertexNormals) const noexcept +int SkinnedEffect::Impl::GetPipelineStatePermutation(uint32_t effectFlags) const noexcept { int permutation = 0; @@ -268,13 +271,13 @@ int SkinnedEffect::Impl::GetPipelineStatePermutation(bool preferPerPixelLighting permutation += 1; } - if (preferPerPixelLighting) + if (effectFlags & EffectFlags::PerPixelLightingBit) { // Do lighting in the pixel shader. permutation += 2; } - if (biasedVertexNormals) + if (effectFlags & EffectFlags::BiasedVertexNormals) { // Compressed normals need to be scaled and biased in the vertex shader. permutation += 4;