diff options
Diffstat (limited to 'lib/win32/Effects11/EffectNonRuntime.cpp')
-rw-r--r-- | lib/win32/Effects11/EffectNonRuntime.cpp | 3023 |
1 files changed, 3023 insertions, 0 deletions
diff --git a/lib/win32/Effects11/EffectNonRuntime.cpp b/lib/win32/Effects11/EffectNonRuntime.cpp new file mode 100644 index 0000000000..3161dfa892 --- /dev/null +++ b/lib/win32/Effects11/EffectNonRuntime.cpp @@ -0,0 +1,3023 @@ +//-------------------------------------------------------------------------------------- +// File: EffectNonRuntime.cpp +// +// D3DX11 Effect low-frequency utility functions +// These functions are not intended to be called regularly. They +// are typically called when creating, cloning, or optimizing an +// Effect, or reflecting a variable. +// +// 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/p/?LinkId=271568 +//-------------------------------------------------------------------------------------- + +#include "pchfx.h" +#include "SOParser.h" + +namespace D3DX11Effects +{ + +extern SUnorderedAccessView g_NullUnorderedAccessView; + +SBaseBlock::SBaseBlock() +: BlockType(EBT_Invalid) +, IsUserManaged(false) +, AssignmentCount(0) +, pAssignments(nullptr) +{ + +} + +SPassBlock::SPassBlock() +{ + pName = nullptr; + AnnotationCount = 0; + pAnnotations = nullptr; + InitiallyValid = true; + HasDependencies = false; + ZeroMemory(&BackingStore, sizeof(BackingStore)); +} + +STechnique::STechnique() +: pName(nullptr) +, PassCount(0) +, pPasses(nullptr) +, AnnotationCount(0) +, pAnnotations(nullptr) +, InitiallyValid( true ) +, HasDependencies( false ) +{ +} + +SGroup::SGroup() +: pName(nullptr) +, TechniqueCount(0) +, pTechniques(nullptr) +, AnnotationCount(0) +, pAnnotations(nullptr) +, InitiallyValid( true ) +, HasDependencies( false ) +{ +} + +SDepthStencilBlock::SDepthStencilBlock() +{ + pDSObject = nullptr; + ZeroMemory(&BackingStore, sizeof(BackingStore)); + IsValid = true; + + BackingStore.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + BackingStore.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + BackingStore.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + BackingStore.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + BackingStore.DepthEnable = true; + BackingStore.DepthFunc = D3D11_COMPARISON_LESS; + BackingStore.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + BackingStore.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + BackingStore.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + BackingStore.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + BackingStore.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + BackingStore.StencilEnable = false; + BackingStore.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + BackingStore.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; +} + +SBlendBlock::SBlendBlock() +{ + pBlendObject = nullptr; + ZeroMemory(&BackingStore, sizeof(BackingStore)); + IsValid = true; + + BackingStore.AlphaToCoverageEnable = false; + BackingStore.IndependentBlendEnable = true; + for( size_t i=0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++ ) + { + BackingStore.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE; + BackingStore.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO; + BackingStore.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; + BackingStore.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; + BackingStore.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO; + BackingStore.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; + memset(&BackingStore.RenderTarget[i].RenderTargetWriteMask, 0x0F, sizeof(BackingStore.RenderTarget[i].RenderTargetWriteMask)); + } +} + +SRasterizerBlock::SRasterizerBlock() +{ + pRasterizerObject = nullptr; + ZeroMemory(&BackingStore, sizeof(BackingStore)); + IsValid = true; + + BackingStore.AntialiasedLineEnable = false; + BackingStore.CullMode = D3D11_CULL_BACK; + BackingStore.DepthBias = D3D11_DEFAULT_DEPTH_BIAS; + BackingStore.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP; + BackingStore.FillMode = D3D11_FILL_SOLID; + BackingStore.FrontCounterClockwise = false; + BackingStore.MultisampleEnable = false; + BackingStore.ScissorEnable = false; + BackingStore.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + BackingStore.DepthClipEnable = true; +} + +SSamplerBlock::SSamplerBlock() +{ + pD3DObject = nullptr; + ZeroMemory(&BackingStore, sizeof(BackingStore)); + + BackingStore.SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + BackingStore.SamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + BackingStore.SamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + BackingStore.SamplerDesc.BorderColor[3] = D3D11_DEFAULT_BORDER_COLOR_COMPONENT; + BackingStore.SamplerDesc.BorderColor[2] = D3D11_DEFAULT_BORDER_COLOR_COMPONENT; + BackingStore.SamplerDesc.BorderColor[1] = D3D11_DEFAULT_BORDER_COLOR_COMPONENT; + BackingStore.SamplerDesc.BorderColor[0] = D3D11_DEFAULT_BORDER_COLOR_COMPONENT; + BackingStore.SamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + BackingStore.SamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + BackingStore.SamplerDesc.MaxAnisotropy = (UINT32) D3D11_DEFAULT_MAX_ANISOTROPY; + BackingStore.SamplerDesc.MipLODBias = D3D11_DEFAULT_MIP_LOD_BIAS; + BackingStore.SamplerDesc.MinLOD = -FLT_MAX; + BackingStore.SamplerDesc.MaxLOD = FLT_MAX; +} + +SShaderBlock::SShaderBlock(SD3DShaderVTable *pVirtualTable) +{ + IsValid = true; + + pVT = pVirtualTable; + + pReflectionData = nullptr; + + pD3DObject = nullptr; + + CBDepCount = 0; + pCBDeps = nullptr; + + SampDepCount = 0; + pSampDeps = nullptr; + + InterfaceDepCount = 0; + pInterfaceDeps = nullptr; + + ResourceDepCount = 0; + pResourceDeps = nullptr; + + UAVDepCount = 0; + pUAVDeps = nullptr; + + TBufferDepCount = 0; + ppTbufDeps = nullptr; + + pInputSignatureBlob = nullptr; +} + +HRESULT SShaderBlock::OnDeviceBind() +{ + HRESULT hr = S_OK; + uint32_t i, j; + + // Update all CB deps + for (i=0; i<CBDepCount; i++) + { + assert(pCBDeps[i].Count); + + for (j=0; j<pCBDeps[i].Count; j++) + { + pCBDeps[i].ppD3DObjects[j] = pCBDeps[i].ppFXPointers[j]->pD3DObject; + + if ( !pCBDeps[i].ppD3DObjects[j] ) + VH( E_FAIL ); + } + } + + // Update all sampler deps + for (i=0; i<SampDepCount; i++) + { + assert(pSampDeps[i].Count); + + for (j=0; j<pSampDeps[i].Count; j++) + { + pSampDeps[i].ppD3DObjects[j] = pSampDeps[i].ppFXPointers[j]->pD3DObject; + + if ( !pSampDeps[i].ppD3DObjects[j] ) + VH( E_FAIL ); + } + } + + // Texture deps will be set automatically on use since they are initially marked dirty. + +lExit: + return hr; +} + +extern SD3DShaderVTable g_vtVS; +extern SD3DShaderVTable g_vtGS; +extern SD3DShaderVTable g_vtPS; +extern SD3DShaderVTable g_vtHS; +extern SD3DShaderVTable g_vtDS; +extern SD3DShaderVTable g_vtCS; + +EObjectType SShaderBlock::GetShaderType() +{ + if (&g_vtVS == pVT) + return EOT_VertexShader; + else if (&g_vtGS == pVT) + return EOT_GeometryShader; + else if (&g_vtPS == pVT) + return EOT_PixelShader; + else if (&g_vtHS == pVT) + return EOT_HullShader5; + else if (&g_vtDS == pVT) + return EOT_DomainShader5; + else if (&g_vtCS == pVT) + return EOT_ComputeShader5; + + return EOT_Invalid; +} + +#define _SET_BIT(bytes, x) (bytes[x / 8] |= (1 << (x % 8))) + +HRESULT SShaderBlock::ComputeStateBlockMask(_Inout_ D3DX11_STATE_BLOCK_MASK *pStateBlockMask) +{ + HRESULT hr = S_OK; + uint32_t i, j; + uint8_t *pSamplerMask = nullptr, *pShaderResourceMask = nullptr, *pConstantBufferMask = nullptr, *pUnorderedAccessViewMask = nullptr, *pInterfaceMask = nullptr; + + switch (GetShaderType()) + { + case EOT_VertexShader: + case EOT_VertexShader5: + pStateBlockMask->VS = 1; + pSamplerMask = pStateBlockMask->VSSamplers; + pShaderResourceMask = pStateBlockMask->VSShaderResources; + pConstantBufferMask = pStateBlockMask->VSConstantBuffers; + pInterfaceMask = pStateBlockMask->VSInterfaces; + pUnorderedAccessViewMask = nullptr; + break; + + case EOT_GeometryShader: + case EOT_GeometryShader5: + pStateBlockMask->GS = 1; + pSamplerMask = pStateBlockMask->GSSamplers; + pShaderResourceMask = pStateBlockMask->GSShaderResources; + pConstantBufferMask = pStateBlockMask->GSConstantBuffers; + pInterfaceMask = pStateBlockMask->GSInterfaces; + pUnorderedAccessViewMask = nullptr; + break; + + case EOT_PixelShader: + case EOT_PixelShader5: + pStateBlockMask->PS = 1; + pSamplerMask = pStateBlockMask->PSSamplers; + pShaderResourceMask = pStateBlockMask->PSShaderResources; + pConstantBufferMask = pStateBlockMask->PSConstantBuffers; + pInterfaceMask = pStateBlockMask->PSInterfaces; + pUnorderedAccessViewMask = &pStateBlockMask->PSUnorderedAccessViews; + break; + + case EOT_HullShader5: + pStateBlockMask->HS = 1; + pSamplerMask = pStateBlockMask->HSSamplers; + pShaderResourceMask = pStateBlockMask->HSShaderResources; + pConstantBufferMask = pStateBlockMask->HSConstantBuffers; + pInterfaceMask = pStateBlockMask->HSInterfaces; + pUnorderedAccessViewMask = nullptr; + break; + + case EOT_DomainShader5: + pStateBlockMask->DS = 1; + pSamplerMask = pStateBlockMask->DSSamplers; + pShaderResourceMask = pStateBlockMask->DSShaderResources; + pConstantBufferMask = pStateBlockMask->DSConstantBuffers; + pInterfaceMask = pStateBlockMask->DSInterfaces; + pUnorderedAccessViewMask = nullptr; + break; + + case EOT_ComputeShader5: + pStateBlockMask->CS = 1; + pSamplerMask = pStateBlockMask->CSSamplers; + pShaderResourceMask = pStateBlockMask->CSShaderResources; + pConstantBufferMask = pStateBlockMask->CSConstantBuffers; + pInterfaceMask = pStateBlockMask->CSInterfaces; + pUnorderedAccessViewMask = &pStateBlockMask->CSUnorderedAccessViews; + break; + + default: + assert(0); + VH(E_FAIL); + } + + for (i = 0; i < SampDepCount; ++ i) + { + for (j = 0; j < pSampDeps[i].Count; ++ j) + { + _SET_BIT(pSamplerMask, (pSampDeps[i].StartIndex + j)); + } + } + + for (i = 0; i < InterfaceDepCount; ++ i) + { + for (j = 0; j < pInterfaceDeps[i].Count; ++ j) + { + _SET_BIT(pInterfaceMask, (pInterfaceDeps[i].StartIndex + j)); + } + } + + for (i = 0; i < ResourceDepCount; ++ i) + { + for (j = 0; j < pResourceDeps[i].Count; ++ j) + { + _SET_BIT(pShaderResourceMask, (pResourceDeps[i].StartIndex + j)); + } + } + + for (i = 0; i < CBDepCount; ++ i) + { + for (j = 0; j < pCBDeps[i].Count; ++ j) + { + _SET_BIT(pConstantBufferMask, (pCBDeps[i].StartIndex + j)); + } + } + + for (i = 0; i < UAVDepCount; ++ i) + { + assert( pUnorderedAccessViewMask != 0 ); + _Analysis_assume_( pUnorderedAccessViewMask != 0 ); + for (j = 0; j < pUAVDeps[i].Count; ++ j) + { + if( pUAVDeps[i].ppFXPointers[j] != &g_NullUnorderedAccessView ) + _SET_BIT(pUnorderedAccessViewMask, (pUAVDeps[i].StartIndex + j)); + } + } + +lExit: + return hr; +} + +#undef _SET_BIT + +HRESULT SShaderBlock::GetShaderDesc(_Out_ D3DX11_EFFECT_SHADER_DESC *pDesc, _In_ bool IsInline) +{ + HRESULT hr = S_OK; + + ZeroMemory(pDesc, sizeof(*pDesc)); + + pDesc->pInputSignature = pInputSignatureBlob ? (const uint8_t*)pInputSignatureBlob->GetBufferPointer() : nullptr; + pDesc->IsInline = IsInline; + + if (nullptr != pReflectionData) + { + // initialize these only if present; otherwise leave them nullptr or 0 + pDesc->pBytecode = pReflectionData->pBytecode; + pDesc->BytecodeLength = pReflectionData->BytecodeLength; + for( size_t iDecl=0; iDecl < D3D11_SO_STREAM_COUNT; ++iDecl ) + { + pDesc->SODecls[iDecl] = pReflectionData->pStreamOutDecls[iDecl]; + } + pDesc->RasterizedStream = pReflectionData->RasterizedStream; + + // get # of input & output signature entries + assert( pReflectionData->pReflection != 0 ); + _Analysis_assume_( pReflectionData->pReflection != 0 ); + + D3D11_SHADER_DESC ShaderDesc; + hr = pReflectionData->pReflection->GetDesc( &ShaderDesc ); + if ( SUCCEEDED(hr) ) + { + pDesc->NumInputSignatureEntries = ShaderDesc.InputParameters; + pDesc->NumOutputSignatureEntries = ShaderDesc.OutputParameters; + pDesc->NumPatchConstantSignatureEntries = ShaderDesc.PatchConstantParameters; + } + } +lExit: + return hr; +} + +HRESULT SShaderBlock::GetVertexShader(_Outptr_ ID3D11VertexShader **ppVS) +{ + if (EOT_VertexShader == GetShaderType() || + EOT_VertexShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppVS = static_cast<ID3D11VertexShader *>( pD3DObject ); + SAFE_ADDREF(*ppVS); + return S_OK; + } + else + { + *ppVS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetVertexShader: This shader variable is not a vertex shader"); + return D3DERR_INVALIDCALL; + } +} + +HRESULT SShaderBlock::GetGeometryShader(_Outptr_ ID3D11GeometryShader **ppGS) +{ + if (EOT_GeometryShader == GetShaderType() || + EOT_GeometryShaderSO == GetShaderType() || + EOT_GeometryShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppGS = static_cast<ID3D11GeometryShader *>( pD3DObject ); + SAFE_ADDREF(*ppGS); + return S_OK; + } + else + { + *ppGS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetGeometryShader: This shader variable is not a geometry shader"); + return D3DERR_INVALIDCALL; + } +} + +HRESULT SShaderBlock::GetPixelShader(_Outptr_ ID3D11PixelShader **ppPS) +{ + if (EOT_PixelShader == GetShaderType() || + EOT_PixelShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppPS = static_cast<ID3D11PixelShader *>( pD3DObject ); + SAFE_ADDREF(*ppPS); + return S_OK; + } + else + { + *ppPS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetPixelShader: This shader variable is not a pixel shader"); + return D3DERR_INVALIDCALL; + } +} + +HRESULT SShaderBlock::GetHullShader(_Outptr_ ID3D11HullShader **ppHS) +{ + if (EOT_HullShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppHS = static_cast<ID3D11HullShader *>( pD3DObject ); + SAFE_ADDREF(*ppHS); + return S_OK; + } + else + { + *ppHS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetHullShader: This shader variable is not a hull shader"); + return D3DERR_INVALIDCALL; + } +} + +HRESULT SShaderBlock::GetDomainShader(_Outptr_ ID3D11DomainShader **ppDS) +{ + if (EOT_DomainShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppDS = static_cast<ID3D11DomainShader *>( pD3DObject ); + SAFE_ADDREF(*ppDS); + return S_OK; + } + else + { + *ppDS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetDomainShader: This shader variable is not a domain shader"); + return D3DERR_INVALIDCALL; + } +} + +HRESULT SShaderBlock::GetComputeShader(_Outptr_ ID3D11ComputeShader **ppCS) +{ + if (EOT_ComputeShader5 == GetShaderType()) + { + assert( pD3DObject != 0 ); + _Analysis_assume_( pD3DObject != 0 ); + *ppCS = static_cast<ID3D11ComputeShader *>( pD3DObject ); + SAFE_ADDREF(*ppCS); + return S_OK; + } + else + { + *ppCS = nullptr; + DPF(0, "ID3DX11EffectShaderVariable::GetComputeShader: This shader variable is not a compute shader"); + return D3DERR_INVALIDCALL; + } +} + +_Use_decl_annotations_ +HRESULT SShaderBlock::GetSignatureElementDesc(ESigType SigType, uint32_t Element, D3D11_SIGNATURE_PARAMETER_DESC *pDesc) +{ + HRESULT hr = S_OK; + LPCSTR pFuncName = nullptr; + switch( SigType ) + { + case ST_Input: + pFuncName = "ID3DX11EffectShaderVariable::GetInputSignatureElementDesc"; + break; + case ST_Output: + pFuncName = "ID3DX11EffectShaderVariable::GetOutputSignatureElementDesc"; + break; + case ST_PatchConstant: + pFuncName = "ID3DX11EffectShaderVariable::GetPatchConstantSignatureElementDesc"; + break; + default: + assert( false ); + return E_FAIL; + }; + + if (nullptr != pReflectionData) + { + // get # of signature entries + assert( pReflectionData->pReflection != 0 ); + _Analysis_assume_( pReflectionData->pReflection != 0 ); + + D3D11_SHADER_DESC ShaderDesc; + VH( pReflectionData->pReflection->GetDesc( &ShaderDesc ) ); + + D3D11_SIGNATURE_PARAMETER_DESC ParamDesc ={0}; + if( pReflectionData->IsNullGS ) + { + switch( SigType ) + { + case ST_Input: + // The input signature for a null-GS is the output signature of the previous VS + SigType = ST_Output; + break; + case ST_PatchConstant: + // GeometryShaders cannot have patch constant signatures + return E_INVALIDARG; + }; + } + + switch( SigType ) + { + case ST_Input: + if( Element >= ShaderDesc.InputParameters ) + { + DPF( 0, "%s: Invalid Element index (%u) specified", pFuncName, Element ); + VH( E_INVALIDARG ); + } + VH( pReflectionData->pReflection->GetInputParameterDesc( Element, &ParamDesc ) ); + break; + case ST_Output: + if( Element >= ShaderDesc.OutputParameters ) + { + DPF( 0, "%s: Invalid Element index (%u) specified", pFuncName, Element ); + VH( E_INVALIDARG ); + } + VH( pReflectionData->pReflection->GetOutputParameterDesc( Element, &ParamDesc ) ); + break; + case ST_PatchConstant: + if( Element >= ShaderDesc.PatchConstantParameters ) + { + DPF( 0, "%s: Invalid Element index (%u) specified", pFuncName, Element ); + VH( E_INVALIDARG ); + } + VH( pReflectionData->pReflection->GetPatchConstantParameterDesc( Element, &ParamDesc ) ); + break; + }; + + pDesc->SemanticName = ParamDesc.SemanticName; + pDesc->SystemValueType = ParamDesc.SystemValueType; + + // Pixel shaders need to be special-cased as they don't technically output SVs + if( pDesc->SystemValueType == D3D_NAME_UNDEFINED && GetShaderType() == EOT_PixelShader && pDesc->SemanticName != 0 ) + { + if( _stricmp(pDesc->SemanticName, "SV_TARGET") == 0 ) + { + pDesc->SystemValueType = D3D_NAME_TARGET; + } + else if( _stricmp(pDesc->SemanticName, "SV_DEPTH") == 0 ) + { + pDesc->SystemValueType = D3D_NAME_DEPTH; + } + else if( _stricmp(pDesc->SemanticName, "SV_COVERAGE") == 0 ) + { + pDesc->SystemValueType = D3D_NAME_COVERAGE; + } + } + + pDesc->SemanticIndex = ParamDesc.SemanticIndex; + pDesc->Register = ParamDesc.Register; + pDesc->Mask = ParamDesc.Mask; + pDesc->ComponentType = ParamDesc.ComponentType; + pDesc->ReadWriteMask = ParamDesc.ReadWriteMask; + } + else + { + DPF(0, "%s: Cannot get signatures; shader bytecode is not present", pFuncName); + VH( D3DERR_INVALIDCALL ); + } + +lExit: + return hr; +} + +SString::SString() +{ + pString = nullptr; +} + +SRenderTargetView::SRenderTargetView() +{ + pRenderTargetView = nullptr; +} + +SDepthStencilView::SDepthStencilView() +{ + pDepthStencilView = nullptr; +} + +void * GetBlockByIndex(EVarType VarType, EObjectType ObjectType, void *pBaseBlock, uint32_t Index) +{ + switch( VarType ) + { + case EVT_Interface: + return (SInterface *)pBaseBlock + Index; + case EVT_Object: + switch (ObjectType) + { + case EOT_Blend: + return (SBlendBlock *)pBaseBlock + Index; + case EOT_DepthStencil: + return (SDepthStencilBlock *)pBaseBlock + Index; + case EOT_Rasterizer: + return (SRasterizerBlock *)pBaseBlock + Index; + case EOT_PixelShader: + case EOT_PixelShader5: + case EOT_GeometryShader: + case EOT_GeometryShaderSO: + case EOT_GeometryShader5: + case EOT_VertexShader: + case EOT_VertexShader5: + case EOT_HullShader5: + case EOT_DomainShader5: + case EOT_ComputeShader5: + return (SShaderBlock *)pBaseBlock + Index; + case EOT_String: + return (SString *)pBaseBlock + Index; + case EOT_Sampler: + return (SSamplerBlock *)pBaseBlock + Index; + case EOT_Buffer: + case EOT_Texture: + case EOT_Texture1D: + case EOT_Texture1DArray: + case EOT_Texture2D: + case EOT_Texture2DArray: + case EOT_Texture2DMS: + case EOT_Texture2DMSArray: + case EOT_Texture3D: + case EOT_TextureCube: + case EOT_TextureCubeArray: + case EOT_ByteAddressBuffer: + case EOT_StructuredBuffer: + return (SShaderResource *)pBaseBlock + Index; + case EOT_DepthStencilView: + return (SDepthStencilView *)pBaseBlock + Index; + case EOT_RenderTargetView: + return (SRenderTargetView *)pBaseBlock + Index; + case EOT_RWTexture1D: + case EOT_RWTexture1DArray: + case EOT_RWTexture2D: + case EOT_RWTexture2DArray: + case EOT_RWTexture3D: + case EOT_RWBuffer: + case EOT_RWByteAddressBuffer: + case EOT_RWStructuredBuffer: + case EOT_RWStructuredBufferAlloc: + case EOT_RWStructuredBufferConsume: + case EOT_AppendStructuredBuffer: + case EOT_ConsumeStructuredBuffer: + return (SUnorderedAccessView *)pBaseBlock + Index; + default: + assert(0); + return nullptr; + } + default: + assert(0); + return nullptr; + } +} + +//-------------------------------------------------------------------------------------- +// CEffect +//-------------------------------------------------------------------------------------- + +CEffect::CEffect( uint32_t Flags ) +{ + m_RefCount = 1; + + m_pVariables = nullptr; + m_pAnonymousShaders = nullptr; + m_pGroups = nullptr; + m_pNullGroup = nullptr; + m_pShaderBlocks = nullptr; + m_pDepthStencilBlocks = nullptr; + m_pBlendBlocks = nullptr; + m_pRasterizerBlocks = nullptr; + m_pSamplerBlocks = nullptr; + m_pCBs = nullptr; + m_pStrings = nullptr; + m_pMemberDataBlocks = nullptr; + m_pInterfaces = nullptr; + m_pShaderResources = nullptr; + m_pUnorderedAccessViews = nullptr; + m_pRenderTargetViews = nullptr; + m_pDepthStencilViews = nullptr; + m_pDevice = nullptr; + m_pClassLinkage = nullptr; + m_pContext = nullptr; + + m_VariableCount = 0; + m_AnonymousShaderCount = 0; + m_ShaderBlockCount = 0; + m_DepthStencilBlockCount = 0; + m_BlendBlockCount = 0; + m_RasterizerBlockCount = 0; + m_SamplerBlockCount = 0; + m_StringCount = 0; + m_MemberDataCount = 0; + m_InterfaceCount = 0; + m_ShaderResourceCount = 0; + m_UnorderedAccessViewCount = 0; + m_RenderTargetViewCount = 0; + m_DepthStencilViewCount = 0; + m_CBCount = 0; + m_TechniqueCount = 0; + m_GroupCount = 0; + + m_pReflection = nullptr; + m_LocalTimer = 1; + m_Flags = Flags; + m_FXLIndex = 0; + + m_pTypePool = nullptr; + m_pStringPool = nullptr; + m_pPooledHeap = nullptr; + m_pOptimizedTypeHeap = nullptr; +} + +void CEffect::ReleaseShaderRefection() +{ + for( size_t i = 0; i < m_ShaderBlockCount; ++ i ) + { + SAFE_RELEASE( m_pShaderBlocks[i].pInputSignatureBlob ); + if( m_pShaderBlocks[i].pReflectionData ) + { + SAFE_RELEASE( m_pShaderBlocks[i].pReflectionData->pReflection ); + } + } +} + +CEffect::~CEffect() +{ + ID3D11InfoQueue *pInfoQueue = nullptr; + + // Mute debug spew + if (m_pDevice) + { + HRESULT hr = m_pDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void**) &pInfoQueue); + if ( FAILED(hr) ) + pInfoQueue = nullptr; + } + + if (pInfoQueue) + { + D3D11_INFO_QUEUE_FILTER filter; + D3D11_MESSAGE_CATEGORY messageCategory = D3D11_MESSAGE_CATEGORY_STATE_SETTING; + ZeroMemory(&filter, sizeof(filter)); + + filter.DenyList.NumCategories = 1; + filter.DenyList.pCategoryList = &messageCategory; + pInfoQueue->PushStorageFilter(&filter); + } + + if( nullptr != m_pDevice ) + { + // if m_pDevice == nullptr, then we failed LoadEffect(), which means ReleaseShaderReflection was already called. + + // Release the shader reflection info, as it was not created on the private heap + // This must be called before we delete m_pReflection + ReleaseShaderRefection(); + } + + SAFE_DELETE( m_pReflection ); + SAFE_DELETE( m_pTypePool ); + SAFE_DELETE( m_pStringPool ); + SAFE_DELETE( m_pPooledHeap ); + SAFE_DELETE( m_pOptimizedTypeHeap ); + + // this code assumes the effect has been loaded & relocated, + // so check for that before freeing the resources + + if (nullptr != m_pDevice) + { + // Keep the following in line with AddRefAllForCloning + + assert(nullptr == m_pRasterizerBlocks || m_Heap.IsInHeap(m_pRasterizerBlocks)); + for (size_t i = 0; i < m_RasterizerBlockCount; ++ i) + { + SAFE_RELEASE(m_pRasterizerBlocks[i].pRasterizerObject); + } + + assert(nullptr == m_pBlendBlocks || m_Heap.IsInHeap(m_pBlendBlocks)); + for (size_t i = 0; i < m_BlendBlockCount; ++ i) + { + SAFE_RELEASE(m_pBlendBlocks[i].pBlendObject); + } + + assert(nullptr == m_pDepthStencilBlocks || m_Heap.IsInHeap(m_pDepthStencilBlocks)); + for (size_t i = 0; i < m_DepthStencilBlockCount; ++ i) + { + SAFE_RELEASE(m_pDepthStencilBlocks[i].pDSObject); + } + + assert(nullptr == m_pSamplerBlocks || m_Heap.IsInHeap(m_pSamplerBlocks)); + for (size_t i = 0; i < m_SamplerBlockCount; ++ i) + { + SAFE_RELEASE(m_pSamplerBlocks[i].pD3DObject); + } + + assert(nullptr == m_pShaderResources || m_Heap.IsInHeap(m_pShaderResources)); + for (size_t i = 0; i < m_ShaderResourceCount; ++ i) + { + SAFE_RELEASE(m_pShaderResources[i].pShaderResource); + } + + assert(nullptr == m_pUnorderedAccessViews || m_Heap.IsInHeap(m_pUnorderedAccessViews)); + for (size_t i = 0; i < m_UnorderedAccessViewCount; ++ i) + { + SAFE_RELEASE(m_pUnorderedAccessViews[i].pUnorderedAccessView); + } + + assert(nullptr == m_pRenderTargetViews || m_Heap.IsInHeap(m_pRenderTargetViews)); + for (size_t i = 0; i < m_RenderTargetViewCount; ++ i) + { + SAFE_RELEASE(m_pRenderTargetViews[i].pRenderTargetView); + } + + assert(nullptr == m_pDepthStencilViews || m_Heap.IsInHeap(m_pDepthStencilViews)); + for (size_t i = 0; i < m_DepthStencilViewCount; ++ i) + { + SAFE_RELEASE(m_pDepthStencilViews[i].pDepthStencilView); + } + + assert(nullptr == m_pMemberDataBlocks || m_Heap.IsInHeap(m_pMemberDataBlocks)); + for (size_t i = 0; i < m_MemberDataCount; ++ i) + { + switch( m_pMemberDataBlocks[i].Type ) + { + case MDT_ClassInstance: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DClassInstance); + break; + case MDT_BlendState: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedBlendState); + break; + case MDT_DepthStencilState: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedDepthStencilState); + break; + case MDT_RasterizerState: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedRasterizerState); + break; + case MDT_SamplerState: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedSamplerState); + break; + case MDT_Buffer: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedConstantBuffer); + break; + case MDT_ShaderResourceView: + SAFE_RELEASE(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedTextureBuffer); + break; + default: + assert( false ); + } + } + + assert(nullptr == m_pCBs || m_Heap.IsInHeap(m_pCBs)); + for (size_t i = 0; i < m_CBCount; ++ i) + { + SAFE_RELEASE(m_pCBs[i].TBuffer.pShaderResource); + SAFE_RELEASE(m_pCBs[i].pD3DObject); + } + + assert(nullptr == m_pShaderBlocks || m_Heap.IsInHeap(m_pShaderBlocks)); + _Analysis_assume_( m_ShaderBlockCount == 0 || m_pShaderBlocks != 0 ); + for (size_t i = 0; i < m_ShaderBlockCount; ++ i) + { + SAFE_RELEASE(m_pShaderBlocks[i].pD3DObject); + } + + SAFE_RELEASE( m_pDevice ); + } + SAFE_RELEASE( m_pClassLinkage ); + assert( m_pContext == nullptr ); + + // Restore debug spew + if (pInfoQueue) + { + pInfoQueue->PopStorageFilter(); + SAFE_RELEASE(pInfoQueue); + } +} + +// AddRef all D3D object when cloning +void CEffect::AddRefAllForCloning( _In_ CEffect* pEffectSource ) +{ +#ifdef NDEBUG + UNREFERENCED_PARAMETER(pEffectSource); +#endif + // Keep the following in line with ~CEffect + + assert( m_pDevice != nullptr ); + + for( size_t i = 0; i < m_ShaderBlockCount; ++ i ) + { + SAFE_ADDREF( m_pShaderBlocks[i].pInputSignatureBlob ); + if( m_pShaderBlocks[i].pReflectionData ) + { + SAFE_ADDREF( m_pShaderBlocks[i].pReflectionData->pReflection ); + } + } + + assert(nullptr == m_pRasterizerBlocks || pEffectSource->m_Heap.IsInHeap(m_pRasterizerBlocks)); + for ( size_t i = 0; i < m_RasterizerBlockCount; ++ i) + { + SAFE_ADDREF(m_pRasterizerBlocks[i].pRasterizerObject); + } + + assert(nullptr == m_pBlendBlocks || pEffectSource->m_Heap.IsInHeap(m_pBlendBlocks)); + for ( size_t i = 0; i < m_BlendBlockCount; ++ i) + { + SAFE_ADDREF(m_pBlendBlocks[i].pBlendObject); + } + + assert(nullptr == m_pDepthStencilBlocks || pEffectSource->m_Heap.IsInHeap(m_pDepthStencilBlocks)); + for ( size_t i = 0; i < m_DepthStencilBlockCount; ++ i) + { + SAFE_ADDREF(m_pDepthStencilBlocks[i].pDSObject); + } + + assert(nullptr == m_pSamplerBlocks || pEffectSource->m_Heap.IsInHeap(m_pSamplerBlocks)); + for ( size_t i = 0; i < m_SamplerBlockCount; ++ i) + { + SAFE_ADDREF(m_pSamplerBlocks[i].pD3DObject); + } + + assert(nullptr == m_pShaderResources || pEffectSource->m_Heap.IsInHeap(m_pShaderResources)); + for ( size_t i = 0; i < m_ShaderResourceCount; ++ i) + { + SAFE_ADDREF(m_pShaderResources[i].pShaderResource); + } + + assert(nullptr == m_pUnorderedAccessViews || pEffectSource->m_Heap.IsInHeap(m_pUnorderedAccessViews)); + for ( size_t i = 0; i < m_UnorderedAccessViewCount; ++ i) + { + SAFE_ADDREF(m_pUnorderedAccessViews[i].pUnorderedAccessView); + } + + assert(nullptr == m_pRenderTargetViews || pEffectSource->m_Heap.IsInHeap(m_pRenderTargetViews)); + for ( size_t i = 0; i < m_RenderTargetViewCount; ++ i) + { + SAFE_ADDREF(m_pRenderTargetViews[i].pRenderTargetView); + } + + assert(nullptr == m_pDepthStencilViews || pEffectSource->m_Heap.IsInHeap(m_pDepthStencilViews)); + for ( size_t i = 0; i < m_DepthStencilViewCount; ++ i) + { + SAFE_ADDREF(m_pDepthStencilViews[i].pDepthStencilView); + } + + assert(nullptr == m_pMemberDataBlocks || pEffectSource->m_Heap.IsInHeap(m_pMemberDataBlocks)); + for ( size_t i = 0; i < m_MemberDataCount; ++ i) + { + switch( m_pMemberDataBlocks[i].Type ) + { + case MDT_ClassInstance: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DClassInstance); + break; + case MDT_BlendState: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedBlendState); + break; + case MDT_DepthStencilState: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedDepthStencilState); + break; + case MDT_RasterizerState: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedRasterizerState); + break; + case MDT_SamplerState: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedSamplerState); + break; + case MDT_Buffer: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedConstantBuffer); + break; + case MDT_ShaderResourceView: + SAFE_ADDREF(m_pMemberDataBlocks[i].Data.pD3DEffectsManagedTextureBuffer); + break; + default: + assert( false ); + } + } + + // There's no need to AddRef CBs, since they are recreated + assert(nullptr == m_pCBs || pEffectSource->m_Heap.IsInHeap(m_pCBs)); + for ( size_t i = 0; i < m_CBCount; ++ i) + { + SAFE_ADDREF(m_pCBs[i].TBuffer.pShaderResource); + SAFE_ADDREF(m_pCBs[i].pD3DObject); + } + + assert(nullptr == m_pShaderBlocks || pEffectSource->m_Heap.IsInHeap(m_pShaderBlocks)); + for ( size_t i = 0; i < m_ShaderBlockCount; ++ i) + { + SAFE_ADDREF(m_pShaderBlocks[i].pD3DObject); + } + + SAFE_ADDREF( m_pDevice ); + + SAFE_ADDREF( m_pClassLinkage ); + assert( m_pContext == nullptr ); +} + +_Use_decl_annotations_ +HRESULT CEffect::QueryInterface(REFIID iid, LPVOID *ppv) +{ + HRESULT hr = S_OK; + + if(nullptr == ppv) + { + DPF(0, "ID3DX11Effect::QueryInterface: nullptr parameter"); + hr = E_INVALIDARG; + goto EXIT; + } + + *ppv = nullptr; + if(IsEqualIID(iid, IID_IUnknown)) + { + *ppv = (IUnknown *) this; + } + else if(IsEqualIID(iid, IID_ID3DX11Effect)) + { + *ppv = (ID3DX11Effect *) this; + } + else + { + return E_NOINTERFACE; + } + + AddRef(); + +EXIT: + return hr; +} + +ULONG CEffect::AddRef() +{ + return ++ m_RefCount; +} + +ULONG CEffect::Release() +{ + if (-- m_RefCount > 0) + { + return m_RefCount; + } + else + { + delete this; + } + + return 0; +} + +// In all shaders, replace pOldBufferBlock with pNewBuffer, if pOldBufferBlock is a dependency +_Use_decl_annotations_ +void CEffect::ReplaceCBReference(SConstantBuffer *pOldBufferBlock, ID3D11Buffer *pNewBuffer) +{ + for (size_t iShaderBlock=0; iShaderBlock<m_ShaderBlockCount; iShaderBlock++) + { + for (size_t iCBDep = 0; iCBDep < m_pShaderBlocks[iShaderBlock].CBDepCount; iCBDep++) + { + for (size_t iCB = 0; iCB < m_pShaderBlocks[iShaderBlock].pCBDeps[iCBDep].Count; iCB++) + { + if (m_pShaderBlocks[iShaderBlock].pCBDeps[iCBDep].ppFXPointers[iCB] == pOldBufferBlock) + m_pShaderBlocks[iShaderBlock].pCBDeps[iCBDep].ppD3DObjects[iCB] = pNewBuffer; + } + } + } +} + +// In all shaders, replace pOldSamplerBlock with pNewSampler, if pOldSamplerBlock is a dependency +_Use_decl_annotations_ +void CEffect::ReplaceSamplerReference(SSamplerBlock *pOldSamplerBlock, ID3D11SamplerState *pNewSampler) +{ + for (size_t iShaderBlock=0; iShaderBlock<m_ShaderBlockCount; iShaderBlock++) + { + for (size_t iSamplerDep = 0; iSamplerDep < m_pShaderBlocks[iShaderBlock].SampDepCount; iSamplerDep++) + { + for (size_t iSampler = 0; iSampler < m_pShaderBlocks[iShaderBlock].pSampDeps[iSamplerDep].Count; iSampler++) + { + if (m_pShaderBlocks[iShaderBlock].pSampDeps[iSamplerDep].ppFXPointers[iSampler] == pOldSamplerBlock) + m_pShaderBlocks[iShaderBlock].pSampDeps[iSamplerDep].ppD3DObjects[iSampler] = pNewSampler; + } + } + } +} + +// Call BindToDevice after the effect has been fully loaded. +// BindToDevice will release all D3D11 objects and create new ones on the new device +_Use_decl_annotations_ +HRESULT CEffect::BindToDevice(ID3D11Device *pDevice, LPCSTR srcName) +{ + HRESULT hr = S_OK; + + // Set new device + if (pDevice == nullptr) + { + DPF(0, "ID3DX11Effect: pDevice must point to a valid D3D11 device"); + return D3DERR_INVALIDCALL; + } + + if (m_pDevice != nullptr) + { + DPF(0, "ID3DX11Effect: Internal error, rebinding effects to a new device is not supported"); + return D3DERR_INVALIDCALL; + } + + bool featureLevelGE11 = ( pDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0 ); + + pDevice->AddRef(); + SAFE_RELEASE(m_pDevice); + m_pDevice = pDevice; + VH( m_pDevice->CreateClassLinkage( &m_pClassLinkage ) ); + SetDebugObjectName(m_pClassLinkage,srcName); + + // Create all constant buffers + SConstantBuffer *pCB = m_pCBs; + SConstantBuffer *pCBLast = m_pCBs + m_CBCount; + for(; pCB != pCBLast; pCB++) + { + SAFE_RELEASE(pCB->pD3DObject); + SAFE_RELEASE(pCB->TBuffer.pShaderResource); + + // This is a CBuffer + if (pCB->Size > 0) + { + if (pCB->IsTBuffer) + { + D3D11_BUFFER_DESC bufDesc; + // size is always register aligned + bufDesc.ByteWidth = pCB->Size; + bufDesc.Usage = D3D11_USAGE_DEFAULT; + bufDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufDesc.CPUAccessFlags = 0; + bufDesc.MiscFlags = 0; + + VH( pDevice->CreateBuffer( &bufDesc, nullptr, &pCB->pD3DObject) ); + SetDebugObjectName(pCB->pD3DObject, srcName ); + + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + viewDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + viewDesc.Buffer.ElementOffset = 0; + viewDesc.Buffer.ElementWidth = pCB->Size / SType::c_RegisterSize; + + VH( pDevice->CreateShaderResourceView( pCB->pD3DObject, &viewDesc, &pCB->TBuffer.pShaderResource) ); + SetDebugObjectName(pCB->TBuffer.pShaderResource, srcName ); + } + else + { + D3D11_BUFFER_DESC bufDesc; + // size is always register aligned + bufDesc.ByteWidth = pCB->Size; + bufDesc.Usage = D3D11_USAGE_DEFAULT; + bufDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufDesc.CPUAccessFlags = 0; + bufDesc.MiscFlags = 0; + + VH( pDevice->CreateBuffer( &bufDesc, nullptr, &pCB->pD3DObject) ); + SetDebugObjectName( pCB->pD3DObject, srcName ); + pCB->TBuffer.pShaderResource = nullptr; + } + + pCB->IsDirty = true; + } + else + { + pCB->IsDirty = false; + } + } + + // Create all RasterizerStates + SRasterizerBlock *pRB = m_pRasterizerBlocks; + SRasterizerBlock *pRBLast = m_pRasterizerBlocks + m_RasterizerBlockCount; + for(; pRB != pRBLast; pRB++) + { + SAFE_RELEASE(pRB->pRasterizerObject); + if( SUCCEEDED( m_pDevice->CreateRasterizerState( &pRB->BackingStore, &pRB->pRasterizerObject) ) ) + { + pRB->IsValid = true; + SetDebugObjectName( pRB->pRasterizerObject, srcName ); + } + else + pRB->IsValid = false; + } + + // Create all DepthStencils + SDepthStencilBlock *pDS = m_pDepthStencilBlocks; + SDepthStencilBlock *pDSLast = m_pDepthStencilBlocks + m_DepthStencilBlockCount; + for(; pDS != pDSLast; pDS++) + { + SAFE_RELEASE(pDS->pDSObject); + if( SUCCEEDED( m_pDevice->CreateDepthStencilState( &pDS->BackingStore, &pDS->pDSObject) ) ) + { + pDS->IsValid = true; + SetDebugObjectName( pDS->pDSObject, srcName ); + } + else + pDS->IsValid = false; + } + + // Create all BlendStates + SBlendBlock *pBlend = m_pBlendBlocks; + SBlendBlock *pBlendLast = m_pBlendBlocks + m_BlendBlockCount; + for(; pBlend != pBlendLast; pBlend++) + { + SAFE_RELEASE(pBlend->pBlendObject); + if( SUCCEEDED( m_pDevice->CreateBlendState( &pBlend->BackingStore, &pBlend->pBlendObject ) ) ) + { + pBlend->IsValid = true; + SetDebugObjectName( pBlend->pBlendObject, srcName ); + } + else + pBlend->IsValid = false; + } + + // Create all Samplers + SSamplerBlock *pSampler = m_pSamplerBlocks; + SSamplerBlock *pSamplerLast = m_pSamplerBlocks + m_SamplerBlockCount; + for(; pSampler != pSamplerLast; pSampler++) + { + SAFE_RELEASE(pSampler->pD3DObject); + + VH( m_pDevice->CreateSamplerState( &pSampler->BackingStore.SamplerDesc, &pSampler->pD3DObject) ); + SetDebugObjectName( pSampler->pD3DObject, srcName ); + } + + // Create all shaders + ID3D11ClassLinkage* neededClassLinkage = featureLevelGE11 ? m_pClassLinkage : nullptr; + SShaderBlock *pShader = m_pShaderBlocks; + SShaderBlock *pShaderLast = m_pShaderBlocks + m_ShaderBlockCount; + for(; pShader != pShaderLast; pShader++) + { + SAFE_RELEASE(pShader->pD3DObject); + + if (nullptr == pShader->pReflectionData) + { + // nullptr shader. It's one of these: + // PixelShader ps; + // or + // SetPixelShader( nullptr ); + continue; + } + + if (pShader->pReflectionData->pStreamOutDecls[0] || pShader->pReflectionData->pStreamOutDecls[1] || + pShader->pReflectionData->pStreamOutDecls[2] || pShader->pReflectionData->pStreamOutDecls[3] ) + { + // This is a geometry shader, process it's data + CSOParser soParser; + VH( soParser.Parse(pShader->pReflectionData->pStreamOutDecls) ); + uint32_t strides[4]; + soParser.GetStrides( strides ); + hr = m_pDevice->CreateGeometryShaderWithStreamOutput(pShader->pReflectionData->pBytecode, + pShader->pReflectionData->BytecodeLength, + soParser.GetDeclArray(), + soParser.GetDeclCount(), + strides, + featureLevelGE11 ? 4 : 1, + pShader->pReflectionData->RasterizedStream, + neededClassLinkage, + reinterpret_cast<ID3D11GeometryShader**>(&pShader->pD3DObject) ); + if (FAILED(hr)) + { + DPF(1, "ID3DX11Effect::Load - failed to create GeometryShader with StreamOutput decl: \"%s\"", soParser.GetErrorString() ); + pShader->IsValid = false; + hr = S_OK; + } + else + { + SetDebugObjectName( pShader->pD3DObject, srcName ); + } + } + else + { + // This is a regular shader + if( pShader->pReflectionData->RasterizedStream == D3D11_SO_NO_RASTERIZED_STREAM ) + pShader->IsValid = false; + else + { + if( FAILED( (m_pDevice->*(pShader->pVT->pCreateShader))( (uint32_t *) pShader->pReflectionData->pBytecode, pShader->pReflectionData->BytecodeLength, neededClassLinkage, &pShader->pD3DObject) ) ) + { + DPF(1, "ID3DX11Effect::Load - failed to create shader" ); + pShader->IsValid = false; + } + else + { + SetDebugObjectName( pShader->pD3DObject, srcName ); + } + } + } + + // Update all dependency pointers + VH( pShader->OnDeviceBind() ); + } + + // Initialize the member data pointers for all variables + uint32_t CurMemberData = 0; + for (uint32_t i = 0; i < m_VariableCount; ++ i) + { + if( m_pVariables[i].pMemberData ) + { + if( m_pVariables[i].pType->IsClassInstance() ) + { + for (uint32_t j = 0; j < std::max<size_t>(m_pVariables[i].pType->Elements,1); ++j) + { + assert( CurMemberData < m_MemberDataCount ); + ID3D11ClassInstance** ppCI = &(m_pVariables[i].pMemberData + j)->Data.pD3DClassInstance; + (m_pVariables[i].pMemberData + j)->Type = MDT_ClassInstance; + (m_pVariables[i].pMemberData + j)->Data.pD3DClassInstance = nullptr; + if( m_pVariables[i].pType->TotalSize > 0 ) + { + // ignore failures in GetClassInstance; + m_pClassLinkage->GetClassInstance( m_pVariables[i].pName, j, ppCI ); + } + else + { + // The HLSL compiler optimizes out zero-sized classes, so we have to create class instances from scratch + if( FAILED( m_pClassLinkage->CreateClassInstance( m_pVariables[i].pType->pTypeName, 0, 0, 0, 0, ppCI ) ) ) + { + DPF(0, "ID3DX11Effect: Out of memory while trying to create new class instance interface"); + } + else + { + SetDebugObjectName( *ppCI, srcName ); + } + } + CurMemberData++; + } + } + else if( m_pVariables[i].pType->IsStateBlockObject() ) + { + for (size_t j = 0; j < std::max<size_t>(m_pVariables[i].pType->Elements,1); ++j) + { + switch( m_pVariables[i].pType->ObjectType ) + { + case EOT_Blend: + (m_pVariables[i].pMemberData + j)->Type = MDT_BlendState; + (m_pVariables[i].pMemberData + j)->Data.pD3DEffectsManagedBlendState = nullptr; + break; + case EOT_Rasterizer: + (m_pVariables[i].pMemberData + j)->Type = MDT_RasterizerState; + (m_pVariables[i].pMemberData + j)->Data.pD3DEffectsManagedRasterizerState = nullptr; + break; + case EOT_DepthStencil: + (m_pVariables[i].pMemberData + j)->Type = MDT_DepthStencilState; + (m_pVariables[i].pMemberData + j)->Data.pD3DEffectsManagedDepthStencilState = nullptr; + break; + case EOT_Sampler: + (m_pVariables[i].pMemberData + j)->Type = MDT_SamplerState; + (m_pVariables[i].pMemberData + j)->Data.pD3DEffectsManagedSamplerState = nullptr; + break; + default: + VB( false ); + } + CurMemberData++; + } + } + else + { + VB( false ); + } + } + } + for(pCB = m_pCBs; pCB != pCBLast; pCB++) + { + (pCB->pMemberData + 0)->Type = MDT_Buffer; + (pCB->pMemberData + 0)->Data.pD3DEffectsManagedConstantBuffer = nullptr; + CurMemberData++; + (pCB->pMemberData + 1)->Type = MDT_ShaderResourceView; + (pCB->pMemberData + 1)->Data.pD3DEffectsManagedTextureBuffer = nullptr; + CurMemberData++; + } + + + // Determine which techniques and passes are known to be invalid + for( size_t iGroup=0; iGroup < m_GroupCount; iGroup++ ) + { + SGroup* pGroup = &m_pGroups[iGroup]; + pGroup->InitiallyValid = true; + + for( size_t iTech=0; iTech < pGroup->TechniqueCount; iTech++ ) + { + STechnique* pTechnique = &pGroup->pTechniques[iTech]; + pTechnique->InitiallyValid = true; + + for( size_t iPass = 0; iPass < pTechnique->PassCount; iPass++ ) + { + SPassBlock* pPass = &pTechnique->pPasses[iPass]; + pPass->InitiallyValid = true; + + if( pPass->BackingStore.pBlendBlock != nullptr && !pPass->BackingStore.pBlendBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pDepthStencilBlock != nullptr && !pPass->BackingStore.pDepthStencilBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pRasterizerBlock != nullptr && !pPass->BackingStore.pRasterizerBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pVertexShaderBlock != nullptr && !pPass->BackingStore.pVertexShaderBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pPixelShaderBlock != nullptr && !pPass->BackingStore.pPixelShaderBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pGeometryShaderBlock != nullptr && !pPass->BackingStore.pGeometryShaderBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pHullShaderBlock != nullptr && !pPass->BackingStore.pHullShaderBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pDomainShaderBlock != nullptr && !pPass->BackingStore.pDomainShaderBlock->IsValid ) + pPass->InitiallyValid = false; + if( pPass->BackingStore.pComputeShaderBlock != nullptr && !pPass->BackingStore.pComputeShaderBlock->IsValid ) + pPass->InitiallyValid = false; + + pTechnique->InitiallyValid &= pPass->InitiallyValid; + } + pGroup->InitiallyValid &= pTechnique->InitiallyValid; + } + } + +lExit: + return hr; +} + +// FindVariableByName, plus an understanding of literal indices +// This code handles A[i]. +// It does not handle anything else, like A.B, A[B[i]], A[B] +SVariable * CEffect::FindVariableByNameWithParsing(_In_z_ LPCSTR pName) +{ + SGlobalVariable *pVariable; + const uint32_t MAX_PARSABLE_NAME_LENGTH = 256; + char pScratchString[MAX_PARSABLE_NAME_LENGTH]; + + const char* pSource = pName; + char* pDest = pScratchString; + char* pEnd = pScratchString + MAX_PARSABLE_NAME_LENGTH; + + pVariable = nullptr; + + while( *pSource != 0 ) + { + if( pDest == pEnd ) + { + pVariable = FindLocalVariableByName(pName); + if( pVariable == nullptr ) + { + DPF( 0, "Name %s is too long to parse", pName ); + } + return pVariable; + } + + if( *pSource == '[' ) + { + // parse previous variable name + *pDest = 0; + assert( pVariable == nullptr ); + pVariable = FindLocalVariableByName(pScratchString); + if( pVariable == nullptr ) + { + return nullptr; + } + pDest = pScratchString; + } + else if( *pSource == ']' ) + { + // parse integer + *pDest = 0; + uint32_t index = atoi(pScratchString); + assert( pVariable != 0 ); + _Analysis_assume_( pVariable != 0 ); + pVariable = (SGlobalVariable*)pVariable->GetElement(index); + if( pVariable && !pVariable->IsValid() ) + { + pVariable = nullptr; + } + return pVariable; + } + else + { + // add character + *pDest = *pSource; + pDest++; + } + pSource++; + } + + if( pDest != pScratchString ) + { + // parse the variable name (there was no [i]) + *pDest = 0; + assert( pVariable == nullptr ); + pVariable = FindLocalVariableByName(pScratchString); + } + + return pVariable; +} + +SGlobalVariable * CEffect::FindVariableByName(_In_z_ LPCSTR pName) +{ + SGlobalVariable *pVariable; + + pVariable = FindLocalVariableByName(pName); + + return pVariable; +} + +SGlobalVariable * CEffect::FindLocalVariableByName(_In_z_ LPCSTR pName) +{ + SGlobalVariable *pVariable, *pVariableEnd; + + pVariableEnd = m_pVariables + m_VariableCount; + for (pVariable = m_pVariables; pVariable != pVariableEnd; pVariable++) + { + if (strcmp( pVariable->pName, pName) == 0) + { + return pVariable; + } + } + + return nullptr; +} + + +// +// Checks to see if two types are equivalent (either at runtime +// or during the type-pooling load process) +// +// Major assumption: if both types are structures, then their +// member types & names should already have been added to the pool, +// in which case their member type & name pointers should be equal. +// +// This is true because complex data types (structures) have all +// sub-types translated before the containing type is translated, +// which means that simple sub-types (numeric types) have already +// been pooled. +// +bool SType::IsEqual(SType *pOtherType) const +{ + if (VarType != pOtherType->VarType || Elements != pOtherType->Elements + || strcmp(pTypeName, pOtherType->pTypeName) != 0) + { + return false; + } + + switch (VarType) + { + case EVT_Struct: + { + if (StructType.Members != pOtherType->StructType.Members) + { + return false; + } + assert(StructType.pMembers != nullptr && pOtherType->StructType.pMembers != nullptr); + + uint32_t i; + for (i = 0; i < StructType.Members; ++ i) + { + // names for types must exist (not true for semantics) + assert(StructType.pMembers[i].pName != nullptr && pOtherType->StructType.pMembers[i].pName != nullptr); + + if (StructType.pMembers[i].pType != pOtherType->StructType.pMembers[i].pType || + StructType.pMembers[i].Data.Offset != pOtherType->StructType.pMembers[i].Data.Offset || + StructType.pMembers[i].pName != pOtherType->StructType.pMembers[i].pName || + StructType.pMembers[i].pSemantic != pOtherType->StructType.pMembers[i].pSemantic) + { + return false; + } + } + } + break; + + case EVT_Object: + { + if (ObjectType != pOtherType->ObjectType) + { + return false; + } + } + break; + + case EVT_Numeric: + { + if (NumericType.Rows != pOtherType->NumericType.Rows || + NumericType.Columns != pOtherType->NumericType.Columns || + NumericType.ScalarType != pOtherType->NumericType.ScalarType || + NumericType.NumericLayout != pOtherType->NumericType.NumericLayout || + NumericType.IsColumnMajor != pOtherType->NumericType.IsColumnMajor || + NumericType.IsPackedArray != pOtherType->NumericType.IsPackedArray) + { + return false; + } + } + break; + + case EVT_Interface: + { + // VarType and pTypeName handled above + } + break; + + default: + { + assert(0); + return false; + } + break; + } + + assert(TotalSize == pOtherType->TotalSize && Stride == pOtherType->Stride && PackedSize == pOtherType->PackedSize); + + return true; +} + +uint32_t SType::GetTotalUnpackedSize(_In_ bool IsSingleElement) const +{ + if (VarType == EVT_Object) + { + return 0; + } + else if (VarType == EVT_Interface) + { + return 0; + } + else if (Elements > 0 && IsSingleElement) + { + assert( ( TotalSize == 0 && Stride == 0 ) || + ( (TotalSize > (Stride * (Elements - 1))) && (TotalSize <= (Stride * Elements)) ) ); + return TotalSize - Stride * (Elements - 1); + } + else + { + return TotalSize; + } +} + +uint32_t SType::GetTotalPackedSize(_In_ bool IsSingleElement) const +{ + if (Elements > 0 && IsSingleElement) + { + assert(PackedSize % Elements == 0); + return PackedSize / Elements; + } + else + { + return PackedSize; + } +} + +SConstantBuffer *CEffect::FindCB(_In_z_ LPCSTR pName) +{ + uint32_t i; + + for (i=0; i<m_CBCount; i++) + { + if (!strcmp(m_pCBs[i].pName, pName)) + { + return &m_pCBs[i]; + } + } + + return nullptr; +} + +bool CEffect::IsOptimized() +{ + if ((m_Flags & D3DX11_EFFECT_OPTIMIZED) != 0) + { + assert(nullptr == m_pReflection); + return true; + } + else + { + assert(nullptr != m_pReflection); + return false; + } +} + +// Replace *ppType with the corresponding value in pMappingTable +// pMappingTable table describes how to map old type pointers to new type pointers +static HRESULT RemapType(_Inout_ SType **ppType, _Inout_ CPointerMappingTable *pMappingTable) +{ + HRESULT hr = S_OK; + + SPointerMapping ptrMapping; + CPointerMappingTable::CIterator iter; + ptrMapping.pOld = *ppType; + VH( pMappingTable->FindValueWithHash(ptrMapping, ptrMapping.Hash(), &iter) ); + *ppType = (SType *) iter.GetData().pNew; + +lExit: + return hr; +} + +// Replace *ppString with the corresponding value in pMappingTable +// pMappingTable table describes how to map old string pointers to new string pointers +static HRESULT RemapString(_In_ char **ppString, _Inout_ CPointerMappingTable *pMappingTable) +{ + HRESULT hr = S_OK; + + SPointerMapping ptrMapping; + CPointerMappingTable::CIterator iter; + ptrMapping.pOld = *ppString; + VH( pMappingTable->FindValueWithHash(ptrMapping, ptrMapping.Hash(), &iter) ); + *ppString = (char *) iter.GetData().pNew; + +lExit: + return hr; +} + +// Used in cloning, copy m_pMemberInterfaces from pEffectSource to this +HRESULT CEffect::CopyMemberInterfaces( _In_ CEffect* pEffectSource ) +{ + HRESULT hr = S_OK; + + uint32_t Members = pEffectSource->m_pMemberInterfaces.GetSize(); + m_pMemberInterfaces.AddRange(Members); + uint32_t i=0; // after a failure, this holds the failing index + for(; i < Members; i++ ) + { + SMember* pOldMember = pEffectSource->m_pMemberInterfaces[i]; + if( pOldMember == nullptr ) + { + // During Optimization, m_pMemberInterfaces[i] was set to nullptr because it was an annotation + m_pMemberInterfaces[i] = nullptr; + continue; + } + + SMember *pNewMember; + assert( pOldMember->pTopLevelEntity != nullptr ); + + if (nullptr == (pNewMember = CreateNewMember((SType*)pOldMember->pType, false))) + { + DPF(0, "ID3DX11Effect: Out of memory while trying to create new member variable interface"); + VN( pNewMember ); + } + + pNewMember->pType = pOldMember->pType; + pNewMember->pName = pOldMember->pName; + pNewMember->pSemantic = pOldMember->pSemantic; + pNewMember->Data.pGeneric = pOldMember->Data.pGeneric; + pNewMember->IsSingleElement = pOldMember->IsSingleElement; + pNewMember->pTopLevelEntity = pOldMember->pTopLevelEntity; + pNewMember->pMemberData = pOldMember->pMemberData; + + m_pMemberInterfaces[i] = pNewMember; + } + +lExit: + if( FAILED(hr) ) + { + assert( i < Members ); + ZeroMemory( &m_pMemberInterfaces[i], sizeof(SMember) * ( Members - i ) ); + } + return hr; +} + +// Used in cloning, copy the string pool from pEffectSource to this and build mappingTable +// for use in RemapString +_Use_decl_annotations_ +HRESULT CEffect::CopyStringPool( CEffect* pEffectSource, CPointerMappingTable& mappingTable ) +{ + HRESULT hr = S_OK; + assert( m_pPooledHeap != 0 ); + _Analysis_assume_( m_pPooledHeap != 0 ); + VN( m_pStringPool = new CEffect::CStringHashTable ); + m_pStringPool->SetPrivateHeap(m_pPooledHeap); + VH( m_pStringPool->AutoGrow() ); + + CStringHashTable::CIterator stringIter; + + // move strings over, build mapping table + for (pEffectSource->m_pStringPool->GetFirstEntry(&stringIter); !pEffectSource->m_pStringPool->PastEnd(&stringIter); pEffectSource->m_pStringPool->GetNextEntry(&stringIter)) + { + SPointerMapping ptrMapping; + char *pString; + + const char* pOldString = stringIter.GetData(); + ptrMapping.pOld = (void*)pOldString; + uint32_t len = (uint32_t)strlen(pOldString); + uint32_t hash = ptrMapping.Hash(); + VN( pString = new(*m_pPooledHeap) char[len + 1] ); + ptrMapping.pNew = (void*)pString; + memcpy(ptrMapping.pNew, ptrMapping.pOld, len + 1); + VH( m_pStringPool->AddValueWithHash(pString, hash) ); + + VH( mappingTable.AddValueWithHash(ptrMapping, hash) ); + } + + // Uncomment to print string mapping + /* + CPointerMappingTable::CIterator mapIter; + for (mappingTable.GetFirstEntry(&mapIter); !mappingTable.PastEnd(&mapIter); mappingTable.GetNextEntry(&mapIter)) + { + SPointerMapping ptrMapping = mapIter.GetData(); + DPF(0, "string: 0x%x : 0x%x %s", (UINT_PTR)ptrMapping.pOld, (UINT_PTR)ptrMapping.pNew, (char*)ptrMapping.pNew ); + }*/ + +lExit: + return hr; +} + +// Used in cloning, copy the unoptimized type pool from pEffectSource to this and build mappingTableTypes +// for use in RemapType. mappingTableStrings is the mapping table previously filled when copying strings. +_Use_decl_annotations_ +HRESULT CEffect::CopyTypePool( CEffect* pEffectSource, CPointerMappingTable& mappingTableTypes, CPointerMappingTable& mappingTableStrings ) +{ + HRESULT hr = S_OK; + assert( m_pPooledHeap != 0 ); + _Analysis_assume_( m_pPooledHeap != 0 ); + VN( m_pTypePool = new CEffect::CTypeHashTable ); + m_pTypePool->SetPrivateHeap(m_pPooledHeap); + VH( m_pTypePool->AutoGrow() ); + + CTypeHashTable::CIterator typeIter; + CPointerMappingTable::CIterator mapIter; + + // first pass: move types over, build mapping table + for (pEffectSource->m_pTypePool->GetFirstEntry(&typeIter); !pEffectSource->m_pTypePool->PastEnd(&typeIter); pEffectSource->m_pTypePool->GetNextEntry(&typeIter)) + { + SPointerMapping ptrMapping; + SType *pType; + + ptrMapping.pOld = typeIter.GetData(); + uint32_t hash = ptrMapping.Hash(); + VN( (ptrMapping.pNew) = new(*m_pPooledHeap) SType ); + memcpy(ptrMapping.pNew, ptrMapping.pOld, sizeof(SType)); + + pType = (SType *) ptrMapping.pNew; + + // if this is a struct, move its members to the newly allocated space + if (EVT_Struct == pType->VarType) + { + SVariable* pOldMembers = pType->StructType.pMembers; + VN( pType->StructType.pMembers = new(*m_pPooledHeap) SVariable[pType->StructType.Members] ); + memcpy(pType->StructType.pMembers, pOldMembers, pType->StructType.Members * sizeof(SVariable)); + } + + VH( m_pTypePool->AddValueWithHash(pType, hash) ); + VH( mappingTableTypes.AddValueWithHash(ptrMapping, hash) ); + } + + // second pass: fixup structure member & name pointers + for (mappingTableTypes.GetFirstEntry(&mapIter); !mappingTableTypes.PastEnd(&mapIter); mappingTableTypes.GetNextEntry(&mapIter)) + { + SPointerMapping ptrMapping = mapIter.GetData(); + + // Uncomment to print type mapping + //DPF(0, "type: 0x%x : 0x%x", (UINT_PTR)ptrMapping.pOld, (UINT_PTR)ptrMapping.pNew ); + + SType *pType = (SType *) ptrMapping.pNew; + + if( pType->pTypeName ) + { + VH( RemapString(&pType->pTypeName, &mappingTableStrings) ); + } + + // if this is a struct, fix up its members' pointers + if (EVT_Struct == pType->VarType) + { + for (uint32_t i = 0; i < pType->StructType.Members; ++ i) + { + VH( RemapType((SType**)&pType->StructType.pMembers[i].pType, &mappingTableTypes) ); + if( pType->StructType.pMembers[i].pName ) + { + VH( RemapString(&pType->StructType.pMembers[i].pName, &mappingTableStrings) ); + } + if( pType->StructType.pMembers[i].pSemantic ) + { + VH( RemapString(&pType->StructType.pMembers[i].pSemantic, &mappingTableStrings) ); + } + } + } + } + +lExit: + return hr; +} + +// Used in cloning, copy the unoptimized type pool from pEffectSource to this and build mappingTableTypes +// for use in RemapType. mappingTableStrings is the mapping table previously filled when copying strings. +_Use_decl_annotations_ +HRESULT CEffect::CopyOptimizedTypePool( CEffect* pEffectSource, CPointerMappingTable& mappingTableTypes ) +{ + HRESULT hr = S_OK; + CEffectHeap* pOptimizedTypeHeap = nullptr; + + assert( pEffectSource->m_pOptimizedTypeHeap != 0 ); + _Analysis_assume_( pEffectSource->m_pOptimizedTypeHeap != 0 ); + assert( m_pTypePool == 0 ); + assert( m_pStringPool == 0 ); + assert( m_pPooledHeap == 0 ); + + VN( pOptimizedTypeHeap = new CEffectHeap ); + VH( pOptimizedTypeHeap->ReserveMemory( pEffectSource->m_pOptimizedTypeHeap->GetSize() ) ); + CPointerMappingTable::CIterator mapIter; + + // first pass: move types over, build mapping table + uint8_t* pReadTypes = pEffectSource->m_pOptimizedTypeHeap->GetDataStart(); + while( pEffectSource->m_pOptimizedTypeHeap->IsInHeap( pReadTypes ) ) + { + SPointerMapping ptrMapping; + SType *pType; + uint32_t moveSize; + + ptrMapping.pOld = ptrMapping.pNew = pReadTypes; + moveSize = sizeof(SType); + VH( pOptimizedTypeHeap->MoveData(&ptrMapping.pNew, moveSize) ); + pReadTypes += moveSize; + + pType = (SType *) ptrMapping.pNew; + + // if this is a struct, move its members to the newly allocated space + if (EVT_Struct == pType->VarType) + { + moveSize = pType->StructType.Members * sizeof(SVariable); + VH( pOptimizedTypeHeap->MoveData((void **)&pType->StructType.pMembers, moveSize) ); + pReadTypes += moveSize; + } + + VH( mappingTableTypes.AddValueWithHash(ptrMapping, ptrMapping.Hash()) ); + } + + // second pass: fixup structure member & name pointers + for (mappingTableTypes.GetFirstEntry(&mapIter); !mappingTableTypes.PastEnd(&mapIter); mappingTableTypes.GetNextEntry(&mapIter)) + { + SPointerMapping ptrMapping = mapIter.GetData(); + + // Uncomment to print type mapping + //DPF(0, "type: 0x%x : 0x%x", (UINT_PTR)ptrMapping.pOld, (UINT_PTR)ptrMapping.pNew ); + + SType *pType = (SType *) ptrMapping.pNew; + + // if this is a struct, fix up its members' pointers + if (EVT_Struct == pType->VarType) + { + for (uint32_t i = 0; i < pType->StructType.Members; ++ i) + { + VH( RemapType((SType**)&pType->StructType.pMembers[i].pType, &mappingTableTypes) ); + } + } + } + +lExit: + return hr; +} + +// Used in cloning, create new ID3D11ConstantBuffers for each non-single CB +HRESULT CEffect::RecreateCBs() +{ + HRESULT hr = S_OK; + uint32_t i; // after a failure, this holds the failing index + + for (i = 0; i < m_CBCount; ++ i) + { + SConstantBuffer* pCB = &m_pCBs[i]; + + pCB->IsNonUpdatable = pCB->IsUserManaged || pCB->ClonedSingle(); + + if( pCB->Size > 0 && !pCB->ClonedSingle() ) + { + ID3D11Buffer** ppOriginalBuffer; + ID3D11ShaderResourceView** ppOriginalTBufferView; + + if( pCB->IsUserManaged ) + { + ppOriginalBuffer = &pCB->pMemberData[0].Data.pD3DEffectsManagedConstantBuffer; + ppOriginalTBufferView = &pCB->pMemberData[1].Data.pD3DEffectsManagedTextureBuffer; + } + else + { + ppOriginalBuffer = &pCB->pD3DObject; + ppOriginalTBufferView = &pCB->TBuffer.pShaderResource; + } + + VN( *ppOriginalBuffer ); + D3D11_BUFFER_DESC bufDesc; + (*ppOriginalBuffer)->GetDesc( &bufDesc ); + ID3D11Buffer* pNewBuffer = nullptr; + VH( m_pDevice->CreateBuffer( &bufDesc, nullptr, &pNewBuffer ) ); + SetDebugObjectName( pNewBuffer, "D3DX11Effect" ); + (*ppOriginalBuffer)->Release(); + (*ppOriginalBuffer) = pNewBuffer; + pNewBuffer = nullptr; + + if( pCB->IsTBuffer ) + { + VN( *ppOriginalTBufferView ); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + (*ppOriginalTBufferView)->GetDesc( &viewDesc ); + ID3D11ShaderResourceView* pNewView = nullptr; + VH( m_pDevice->CreateShaderResourceView( (*ppOriginalBuffer), &viewDesc, &pNewView) ); + SetDebugObjectName( pNewView, "D3DX11Effect" ); + (*ppOriginalTBufferView)->Release(); + (*ppOriginalTBufferView) = pNewView; + pNewView = nullptr; + } + else + { + assert( *ppOriginalTBufferView == nullptr ); + ReplaceCBReference( pCB, (*ppOriginalBuffer) ); + } + + pCB->IsDirty = true; + } + } + +lExit: + return hr; +} + +// Move Name and Semantic strings using mappingTableStrings +_Use_decl_annotations_ +HRESULT CEffect::FixupMemberInterface( SMember* pMember, CEffect* pEffectSource, CPointerMappingTable& mappingTableStrings ) +{ + HRESULT hr = S_OK; + + if( pMember->pName ) + { + if( pEffectSource->m_pReflection && pEffectSource->m_pReflection->m_Heap.IsInHeap(pMember->pName) ) + { + pMember->pName = (char*)((UINT_PTR)pMember->pName - (UINT_PTR)pEffectSource->m_pReflection->m_Heap.GetDataStart() + (UINT_PTR)m_pReflection->m_Heap.GetDataStart()); + } + else + { + VH( RemapString(&pMember->pName, &mappingTableStrings) ); + } + } + if( pMember->pSemantic ) + { + if( pEffectSource->m_pReflection && pEffectSource->m_pReflection->m_Heap.IsInHeap(pMember->pSemantic) ) + { + pMember->pSemantic = (char*)((UINT_PTR)pMember->pSemantic - (UINT_PTR)pEffectSource->m_pReflection->m_Heap.GetDataStart() + (UINT_PTR)m_pReflection->m_Heap.GetDataStart()); + } + else + { + VH( RemapString(&pMember->pSemantic, &mappingTableStrings) ); + } + } + +lExit: + return hr; +} + +////////////////////////////////////////////////////////////////////////// +// Public API to create a copy of this effect +HRESULT CEffect::CloneEffect(_In_ uint32_t Flags, _Outptr_ ID3DX11Effect** ppClonedEffect ) +{ + HRESULT hr = S_OK; + CPointerMappingTable mappingTableTypes; + CPointerMappingTable mappingTableStrings; + + CEffectLoader loader; + CEffect* pNewEffect = nullptr; + CDataBlockStore* pTempHeap = nullptr; + + + VN( pNewEffect = new CEffect( m_Flags ) ); + if( Flags & D3DX11_EFFECT_CLONE_FORCE_NONSINGLE ) + { + // The effect is cloned as if there was no original, so don't mark it as cloned + pNewEffect->m_Flags &= ~(uint32_t)D3DX11_EFFECT_CLONE; + } + else + { + pNewEffect->m_Flags |= D3DX11_EFFECT_CLONE; + } + + pNewEffect->m_VariableCount = m_VariableCount; + pNewEffect->m_pVariables = m_pVariables; + pNewEffect->m_AnonymousShaderCount = m_AnonymousShaderCount; + pNewEffect->m_pAnonymousShaders = m_pAnonymousShaders; + pNewEffect->m_TechniqueCount = m_TechniqueCount; + pNewEffect->m_GroupCount = m_GroupCount; + pNewEffect->m_pGroups = m_pGroups; + pNewEffect->m_pNullGroup = m_pNullGroup; + pNewEffect->m_ShaderBlockCount = m_ShaderBlockCount; + pNewEffect->m_pShaderBlocks = m_pShaderBlocks; + pNewEffect->m_DepthStencilBlockCount = m_DepthStencilBlockCount; + pNewEffect->m_pDepthStencilBlocks = m_pDepthStencilBlocks; + pNewEffect->m_BlendBlockCount = m_BlendBlockCount; + pNewEffect->m_pBlendBlocks = m_pBlendBlocks; + pNewEffect->m_RasterizerBlockCount = m_RasterizerBlockCount; + pNewEffect->m_pRasterizerBlocks = m_pRasterizerBlocks; + pNewEffect->m_SamplerBlockCount = m_SamplerBlockCount; + pNewEffect->m_pSamplerBlocks = m_pSamplerBlocks; + pNewEffect->m_MemberDataCount = m_MemberDataCount; + pNewEffect->m_pMemberDataBlocks = m_pMemberDataBlocks; + pNewEffect->m_InterfaceCount = m_InterfaceCount; + pNewEffect->m_pInterfaces = m_pInterfaces; + pNewEffect->m_CBCount = m_CBCount; + pNewEffect->m_pCBs = m_pCBs; + pNewEffect->m_StringCount = m_StringCount; + pNewEffect->m_pStrings = m_pStrings; + pNewEffect->m_ShaderResourceCount = m_ShaderResourceCount; + pNewEffect->m_pShaderResources = m_pShaderResources; + pNewEffect->m_UnorderedAccessViewCount = m_UnorderedAccessViewCount; + pNewEffect->m_pUnorderedAccessViews = m_pUnorderedAccessViews; + pNewEffect->m_RenderTargetViewCount = m_RenderTargetViewCount; + pNewEffect->m_pRenderTargetViews = m_pRenderTargetViews; + pNewEffect->m_DepthStencilViewCount = m_DepthStencilViewCount; + pNewEffect->m_pDepthStencilViews = m_pDepthStencilViews; + pNewEffect->m_LocalTimer = m_LocalTimer; + pNewEffect->m_FXLIndex = m_FXLIndex; + pNewEffect->m_pDevice = m_pDevice; + pNewEffect->m_pClassLinkage = m_pClassLinkage; + + pNewEffect->AddRefAllForCloning( this ); + + + // m_pMemberInterfaces is a vector of cbuffer members that were created when the user called GetMemberBy* or GetElement + // or during Effect loading when an interface is initialized to a global class variable elment. + VH( pNewEffect->CopyMemberInterfaces( this ) ); + + loader.m_pvOldMemberInterfaces = &m_pMemberInterfaces; + loader.m_pEffect = pNewEffect; + loader.m_EffectMemory = loader.m_ReflectionMemory = 0; + + + // Move data from current effect to new effect + if( !IsOptimized() ) + { + VN( pNewEffect->m_pReflection = new CEffectReflection() ); + loader.m_pReflection = pNewEffect->m_pReflection; + + // make sure strings are moved before ReallocateEffectData + VH( loader.InitializeReflectionDataAndMoveStrings( m_pReflection->m_Heap.GetSize() ) ); + } + VH( loader.ReallocateEffectData( true ) ); + if( !IsOptimized() ) + { + VH( loader.ReallocateReflectionData( true ) ); + } + + + // Data structures for remapping type pointers and string pointers + VN( pTempHeap = new CDataBlockStore ); + pTempHeap->EnableAlignment(); + mappingTableTypes.SetPrivateHeap(pTempHeap); + mappingTableStrings.SetPrivateHeap(pTempHeap); + VH( mappingTableTypes.AutoGrow() ); + VH( mappingTableStrings.AutoGrow() ); + + if( !IsOptimized() ) + { + // Let's re-create the type pool and string pool + VN( pNewEffect->m_pPooledHeap = new CDataBlockStore ); + pNewEffect->m_pPooledHeap->EnableAlignment(); + + VH( pNewEffect->CopyStringPool( this, mappingTableStrings ) ); + VH( pNewEffect->CopyTypePool( this, mappingTableTypes, mappingTableStrings ) ); + } + else + { + // There's no string pool after optimizing. Let's re-create the type pool + VH( pNewEffect->CopyOptimizedTypePool( this, mappingTableTypes ) ); + } + + // fixup this effect's variable's types + VH( pNewEffect->OptimizeTypes(&mappingTableTypes, true) ); + VH( pNewEffect->RecreateCBs() ); + + + for (uint32_t i = 0; i < pNewEffect->m_pMemberInterfaces.GetSize(); ++ i) + { + SMember* pMember = pNewEffect->m_pMemberInterfaces[i]; + VH( pNewEffect->FixupMemberInterface( pMember, this, mappingTableStrings ) ); + } + + +lExit: + SAFE_DELETE( pTempHeap ); + if( FAILED( hr ) ) + { + SAFE_DELETE( pNewEffect ); + } + *ppClonedEffect = pNewEffect; + return hr; +} + +// Move all type pointers using pMappingTable. +// This is called after creating the optimized type pool or during cloning. +HRESULT CEffect::OptimizeTypes(_Inout_ CPointerMappingTable *pMappingTable, _In_ bool Cloning) +{ + HRESULT hr = S_OK; + + // find all child types, point them to the new location + for (size_t i = 0; i < m_VariableCount; ++ i) + { + VH( RemapType((SType**)&m_pVariables[i].pType, pMappingTable) ); + } + + uint32_t Members = m_pMemberInterfaces.GetSize(); + for( size_t i=0; i < Members; i++ ) + { + if( m_pMemberInterfaces[i] != nullptr ) + { + VH( RemapType((SType**)&m_pMemberInterfaces[i]->pType, pMappingTable) ); + } + } + + // when cloning, there may be annotations + if( Cloning ) + { + for (size_t iVar = 0; iVar < m_VariableCount; ++ iVar) + { + for(size_t i = 0; i < m_pVariables[iVar].AnnotationCount; ++ i ) + { + VH( RemapType((SType**)&m_pVariables[iVar].pAnnotations[i].pType, pMappingTable) ); + } + } + for (size_t iCB = 0; iCB < m_CBCount; ++ iCB) + { + for(size_t i = 0; i < m_pCBs[iCB].AnnotationCount; ++ i ) + { + VH( RemapType((SType**)&m_pCBs[iCB].pAnnotations[i].pType, pMappingTable) ); + } + } + for (size_t iGroup = 0; iGroup < m_GroupCount; ++ iGroup) + { + for(size_t i = 0; i < m_pGroups[iGroup].AnnotationCount; ++ i ) + { + VH( RemapType((SType**)&m_pGroups[iGroup].pAnnotations[i].pType, pMappingTable) ); + } + for(size_t iTech = 0; iTech < m_pGroups[iGroup].TechniqueCount; ++ iTech ) + { + for(size_t i = 0; i < m_pGroups[iGroup].pTechniques[iTech].AnnotationCount; ++ i ) + { + VH( RemapType((SType**)&m_pGroups[iGroup].pTechniques[iTech].pAnnotations[i].pType, pMappingTable) ); + } + for(size_t iPass = 0; iPass < m_pGroups[iGroup].pTechniques[iTech].PassCount; ++ iPass ) + { + for(size_t i = 0; i < m_pGroups[iGroup].pTechniques[iTech].pPasses[iPass].AnnotationCount; ++ i ) + { + VH( RemapType((SType**)&m_pGroups[iGroup].pTechniques[iTech].pPasses[iPass].pAnnotations[i].pType, pMappingTable) ); + } + } + } + } + } +lExit: + return hr; +} + +////////////////////////////////////////////////////////////////////////// +// Public API to shed this effect of its reflection data + +HRESULT CEffect::Optimize() +{ + HRESULT hr = S_OK; + CEffectHeap *pOptimizedTypeHeap = nullptr; + + if (IsOptimized()) + { + DPF(0, "ID3DX11Effect::Optimize: Effect has already been Optimize()'ed"); + return S_OK; + } + + // Delete annotations, names, semantics, and string data on variables + + for (size_t i = 0; i < m_VariableCount; ++ i) + { + m_pVariables[i].AnnotationCount = 0; + m_pVariables[i].pAnnotations = nullptr; + m_pVariables[i].pName = nullptr; + m_pVariables[i].pSemantic = nullptr; + + // 2) Point string variables to nullptr + if (m_pVariables[i].pType->IsObjectType(EOT_String)) + { + assert(nullptr != m_pVariables[i].Data.pString); + m_pVariables[i].Data.pString = nullptr; + } + } + + // Delete annotations and names on CBs + + for (size_t i = 0; i < m_CBCount; ++ i) + { + m_pCBs[i].AnnotationCount = 0; + m_pCBs[i].pAnnotations = nullptr; + m_pCBs[i].pName = nullptr; + m_pCBs[i].IsEffectOptimized = true; + } + + // Delete annotations and names on techniques and passes + + for (size_t i = 0; i < m_GroupCount; ++ i) + { + m_pGroups[i].AnnotationCount = 0; + m_pGroups[i].pAnnotations = nullptr; + m_pGroups[i].pName = nullptr; + + for (size_t j = 0; j < m_pGroups[i].TechniqueCount; ++ j) + { + m_pGroups[i].pTechniques[j].AnnotationCount = 0; + m_pGroups[i].pTechniques[j].pAnnotations = nullptr; + m_pGroups[i].pTechniques[j].pName = nullptr; + + for (size_t k = 0; k < m_pGroups[i].pTechniques[j].PassCount; ++ k) + { + m_pGroups[i].pTechniques[j].pPasses[k].AnnotationCount = 0; + m_pGroups[i].pTechniques[j].pPasses[k].pAnnotations = nullptr; + m_pGroups[i].pTechniques[j].pPasses[k].pName = nullptr; + } + } + }; + + // 2) Remove shader bytecode & stream out decls + // (all are contained within pReflectionData) + + for (size_t i = 0; i < m_ShaderBlockCount; ++ i) + { + if( m_pShaderBlocks[i].pReflectionData ) + { + // pReflection was not created with PRIVATENEW + SAFE_RELEASE( m_pShaderBlocks[i].pReflectionData->pReflection ); + + m_pShaderBlocks[i].pReflectionData = nullptr; + } + } + + uint32_t Members = m_pMemberInterfaces.GetSize(); + for( size_t i=0; i < Members; i++ ) + { + assert( m_pMemberInterfaces[i] != nullptr ); + if( IsReflectionData(m_pMemberInterfaces[i]->pTopLevelEntity) ) + { + assert( IsReflectionData(m_pMemberInterfaces[i]->Data.pGeneric) ); + + // This is checked when cloning (so we don't clone Optimized-out member variables) + m_pMemberInterfaces[i] = nullptr; + } + else + { + m_pMemberInterfaces[i]->pName = nullptr; + m_pMemberInterfaces[i]->pSemantic = nullptr; + } + } + + + + // get rid of the name/type hash tables and string data, + // then reallocate the type data and fix up this effect + CPointerMappingTable mappingTable; + CTypeHashTable::CIterator typeIter; + CPointerMappingTable::CIterator mapIter; + CCheckedDword chkSpaceNeeded = 0; + uint32_t spaceNeeded; + + // first pass: compute needed space + for (m_pTypePool->GetFirstEntry(&typeIter); !m_pTypePool->PastEnd(&typeIter); m_pTypePool->GetNextEntry(&typeIter)) + { + SType *pType = typeIter.GetData(); + + chkSpaceNeeded += AlignToPowerOf2(sizeof(SType), c_DataAlignment); + + // if this is a struct, allocate room for its members + if (EVT_Struct == pType->VarType) + { + chkSpaceNeeded += AlignToPowerOf2(pType->StructType.Members * sizeof(SVariable), c_DataAlignment); + } + } + + VH( chkSpaceNeeded.GetValue(&spaceNeeded) ); + + assert(nullptr == m_pOptimizedTypeHeap); + VN( pOptimizedTypeHeap = new CEffectHeap ); + VH( pOptimizedTypeHeap->ReserveMemory(spaceNeeded)); + + // use the private heap that we're about to destroy as scratch space for the mapping table + mappingTable.SetPrivateHeap(m_pPooledHeap); + VH( mappingTable.AutoGrow() ); + + // second pass: move types over, build mapping table + for (m_pTypePool->GetFirstEntry(&typeIter); !m_pTypePool->PastEnd(&typeIter); m_pTypePool->GetNextEntry(&typeIter)) + { + SPointerMapping ptrMapping; + SType *pType; + + ptrMapping.pOld = ptrMapping.pNew = typeIter.GetData(); + VH( pOptimizedTypeHeap->MoveData(&ptrMapping.pNew, sizeof(SType)) ); + + pType = (SType *) ptrMapping.pNew; + + // if this is a struct, move its members to the newly allocated space + if (EVT_Struct == pType->VarType) + { + VH( pOptimizedTypeHeap->MoveData((void **)&pType->StructType.pMembers, pType->StructType.Members * sizeof(SVariable)) ); + } + + VH( mappingTable.AddValueWithHash(ptrMapping, ptrMapping.Hash()) ); + } + + // third pass: fixup structure member & name pointers + for (mappingTable.GetFirstEntry(&mapIter); !mappingTable.PastEnd(&mapIter); mappingTable.GetNextEntry(&mapIter)) + { + SPointerMapping ptrMapping = mapIter.GetData(); + SType *pType = (SType *) ptrMapping.pNew; + + pType->pTypeName = nullptr; + + // if this is a struct, fix up its members' pointers + if (EVT_Struct == pType->VarType) + { + for (size_t i = 0; i < pType->StructType.Members; ++ i) + { + VH( RemapType((SType**)&pType->StructType.pMembers[i].pType, &mappingTable) ); + pType->StructType.pMembers[i].pName = nullptr; + pType->StructType.pMembers[i].pSemantic = nullptr; + } + } + } + + // fixup this effect's variable's types + VH( OptimizeTypes(&mappingTable) ); + + m_pOptimizedTypeHeap = pOptimizedTypeHeap; + pOptimizedTypeHeap = nullptr; + +#ifdef D3DX11_FX_PRINT_HASH_STATS + DPF(0, "Compiler string pool hash table statistics:"); + m_pTypePool->PrintHashTableStats(); + DPF(0, "Compiler type pool hash table statistics:"); + m_pStringPool->PrintHashTableStats(); +#endif // D3DX11_FX_PRINT_HASH_STATS + + SAFE_DELETE(m_pTypePool); + SAFE_DELETE(m_pStringPool); + SAFE_DELETE(m_pPooledHeap); + + DPF(0, "ID3DX11Effect::Optimize: %u bytes of reflection data freed.", m_pReflection->m_Heap.GetSize()); + SAFE_DELETE(m_pReflection); + m_Flags |= D3DX11_EFFECT_OPTIMIZED; + +lExit: + SAFE_DELETE(pOptimizedTypeHeap); + return hr; +} + +SMember * CreateNewMember(_In_ SType *pType, _In_ bool IsAnnotation) +{ + switch (pType->VarType) + { + case EVT_Struct: + if (IsAnnotation) + { + assert(sizeof(SNumericAnnotationMember) == sizeof(SMember)); + return (SMember*) new SNumericAnnotationMember; + } + else if (pType->StructType.ImplementsInterface) + { + assert(sizeof(SClassInstanceGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SClassInstanceGlobalVariableMember; + } + else + { + assert(sizeof(SNumericGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SNumericGlobalVariableMember; + } + break; + case EVT_Interface: + assert(sizeof(SInterfaceGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SInterfaceGlobalVariableMember; + break; + case EVT_Object: + switch (pType->ObjectType) + { + case EOT_String: + if (IsAnnotation) + { + assert(sizeof(SStringAnnotationMember) == sizeof(SMember)); + return (SMember*) new SStringAnnotationMember; + } + else + { + assert(sizeof(SStringGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SStringGlobalVariableMember; + } + + break; + case EOT_Texture: + case EOT_Texture1D: + case EOT_Texture1DArray: + case EOT_Texture2D: + case EOT_Texture2DArray: + case EOT_Texture2DMS: + case EOT_Texture2DMSArray: + case EOT_Texture3D: + case EOT_TextureCube: + case EOT_TextureCubeArray: + case EOT_Buffer: + case EOT_ByteAddressBuffer: + case EOT_StructuredBuffer: + assert(!IsAnnotation); + assert(sizeof(SShaderResourceGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SShaderResourceGlobalVariableMember; + break; + case EOT_RWTexture1D: + case EOT_RWTexture1DArray: + case EOT_RWTexture2D: + case EOT_RWTexture2DArray: + case EOT_RWTexture3D: + case EOT_RWBuffer: + case EOT_RWByteAddressBuffer: + case EOT_RWStructuredBuffer: + case EOT_RWStructuredBufferAlloc: + case EOT_RWStructuredBufferConsume: + case EOT_AppendStructuredBuffer: + case EOT_ConsumeStructuredBuffer: + assert(!IsAnnotation); + assert(sizeof(SUnorderedAccessViewGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SUnorderedAccessViewGlobalVariableMember; + break; + case EOT_VertexShader: + case EOT_VertexShader5: + case EOT_GeometryShader: + case EOT_GeometryShaderSO: + case EOT_GeometryShader5: + case EOT_PixelShader: + case EOT_PixelShader5: + case EOT_HullShader5: + case EOT_DomainShader5: + case EOT_ComputeShader5: + assert(!IsAnnotation); + assert(sizeof(SShaderGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SShaderGlobalVariableMember; + break; + case EOT_Blend: + assert(!IsAnnotation); + assert(sizeof(SBlendGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SBlendGlobalVariableMember; + break; + case EOT_Rasterizer: + assert(!IsAnnotation); + assert(sizeof(SRasterizerGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SRasterizerGlobalVariableMember; + break; + case EOT_DepthStencil: + assert(!IsAnnotation); + assert(sizeof(SDepthStencilGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SDepthStencilGlobalVariableMember; + break; + case EOT_Sampler: + assert(!IsAnnotation); + assert(sizeof(SSamplerGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SSamplerGlobalVariableMember; + break; + case EOT_DepthStencilView: + assert(!IsAnnotation); + assert(sizeof(SDepthStencilViewGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SDepthStencilViewGlobalVariableMember; + break; + case EOT_RenderTargetView: + assert(!IsAnnotation); + assert(sizeof(SRenderTargetViewGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SRenderTargetViewGlobalVariableMember; + break; + default: + assert(0); + DPF( 0, "Internal error: invalid object type." ); + return nullptr; + break; + } + break; + case EVT_Numeric: + switch (pType->NumericType.NumericLayout) + { + case ENL_Matrix: + if (IsAnnotation) + { + assert(sizeof(SMatrixAnnotationMember) == sizeof(SMember)); + return (SMember*) new SMatrixAnnotationMember; + } + else + { + assert(sizeof(SMatrixGlobalVariableMember) == sizeof(SMember)); + assert(sizeof(SMatrix4x4ColumnMajorGlobalVariableMember) == sizeof(SMember)); + assert(sizeof(SMatrix4x4RowMajorGlobalVariableMember) == sizeof(SMember)); + + if (pType->NumericType.Rows == 4 && pType->NumericType.Columns == 4) + { + if (pType->NumericType.IsColumnMajor) + { + return (SMember*) new SMatrix4x4ColumnMajorGlobalVariableMember; + } + else + { + return (SMember*) new SMatrix4x4RowMajorGlobalVariableMember; + } + } + else + { + return (SMember*) new SMatrixGlobalVariableMember; + } + } + break; + case ENL_Vector: + switch (pType->NumericType.ScalarType) + { + case EST_Float: + if (IsAnnotation) + { + assert(sizeof(SFloatVectorAnnotationMember) == sizeof(SMember)); + return (SMember*) new SFloatVectorAnnotationMember; + } + else + { + assert(sizeof(SFloatVectorGlobalVariableMember) == sizeof(SMember)); + assert(sizeof(SFloatVector4GlobalVariableMember) == sizeof(SMember)); + + if (pType->NumericType.Columns == 4) + { + return (SMember*) new SFloatVector4GlobalVariableMember; + } + else + { + return (SMember*) new SFloatVectorGlobalVariableMember; + } + } + break; + case EST_Bool: + if (IsAnnotation) + { + assert(sizeof(SBoolVectorAnnotationMember) == sizeof(SMember)); + return (SMember*) new SBoolVectorAnnotationMember; + } + else + { + assert(sizeof(SBoolVectorGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SBoolVectorGlobalVariableMember; + } + break; + case EST_UInt: + case EST_Int: + if (IsAnnotation) + { + assert(sizeof(SIntVectorAnnotationMember) == sizeof(SMember)); + return (SMember*) new SIntVectorAnnotationMember; + } + else + { + assert(sizeof(SIntVectorGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SIntVectorGlobalVariableMember; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid vector type." ); + break; + } + break; + case ENL_Scalar: + switch (pType->NumericType.ScalarType) + { + case EST_Float: + if (IsAnnotation) + { + assert(sizeof(SFloatScalarAnnotationMember) == sizeof(SMember)); + return (SMember*) new SFloatScalarAnnotationMember; + } + else + { + assert(sizeof(SFloatScalarGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SFloatScalarGlobalVariableMember; + } + break; + case EST_UInt: + case EST_Int: + if (IsAnnotation) + { + assert(sizeof(SIntScalarAnnotationMember) == sizeof(SMember)); + return (SMember*) new SIntScalarAnnotationMember; + } + else + { + assert(sizeof(SIntScalarGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SIntScalarGlobalVariableMember; + } + break; + case EST_Bool: + if (IsAnnotation) + { + assert(sizeof(SBoolScalarAnnotationMember) == sizeof(SMember)); + return (SMember*) new SBoolScalarAnnotationMember; + } + else + { + assert(sizeof(SBoolScalarGlobalVariableMember) == sizeof(SMember)); + return (SMember*) new SBoolScalarGlobalVariableMember; + } + break; + default: + DPF( 0, "Internal loading error: invalid scalar type." ); + assert(0); + break; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid numeric type." ); + break; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid variable type." ); + break; + } + return nullptr; +} + +// Global variables are created in place because storage for them was allocated during LoadEffect +HRESULT PlacementNewVariable(_In_ void *pVar, _In_ SType *pType, _In_ bool IsAnnotation) +{ + switch (pType->VarType) + { + case EVT_Struct: + if (IsAnnotation) + { + assert(sizeof(SNumericAnnotation) == sizeof(SAnnotation)); + new(pVar) SNumericAnnotation(); + } + else if (pType->StructType.ImplementsInterface) + { + assert(sizeof(SClassInstanceGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SClassInstanceGlobalVariable; + } + else + { + assert(sizeof(SNumericGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SNumericGlobalVariable; + } + break; + case EVT_Interface: + assert(sizeof(SInterfaceGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SInterfaceGlobalVariable; + break; + case EVT_Object: + switch (pType->ObjectType) + { + case EOT_String: + if (IsAnnotation) + { + assert(sizeof(SStringAnnotation) == sizeof(SAnnotation)); + new(pVar) SStringAnnotation; + } + else + { + assert(sizeof(SStringGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SStringGlobalVariable; + } + + break; + case EOT_Texture: + case EOT_Texture1D: + case EOT_Texture1DArray: + case EOT_Texture2D: + case EOT_Texture2DArray: + case EOT_Texture2DMS: + case EOT_Texture2DMSArray: + case EOT_Texture3D: + case EOT_TextureCube: + case EOT_TextureCubeArray: + case EOT_Buffer: + case EOT_ByteAddressBuffer: + case EOT_StructuredBuffer: + assert(!IsAnnotation); + assert(sizeof(SShaderResourceGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SShaderResourceGlobalVariable; + break; + case EOT_RWTexture1D: + case EOT_RWTexture1DArray: + case EOT_RWTexture2D: + case EOT_RWTexture2DArray: + case EOT_RWTexture3D: + case EOT_RWBuffer: + case EOT_RWByteAddressBuffer: + case EOT_RWStructuredBuffer: + case EOT_RWStructuredBufferAlloc: + case EOT_RWStructuredBufferConsume: + case EOT_AppendStructuredBuffer: + case EOT_ConsumeStructuredBuffer: + assert(!IsAnnotation); + assert(sizeof(SUnorderedAccessViewGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SUnorderedAccessViewGlobalVariable; + break; + case EOT_VertexShader: + case EOT_VertexShader5: + case EOT_GeometryShader: + case EOT_GeometryShaderSO: + case EOT_GeometryShader5: + case EOT_PixelShader: + case EOT_PixelShader5: + case EOT_HullShader5: + case EOT_DomainShader5: + case EOT_ComputeShader5: + assert(!IsAnnotation); + assert(sizeof(SShaderGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SShaderGlobalVariable; + break; + case EOT_Blend: + assert(!IsAnnotation); + assert(sizeof(SBlendGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SBlendGlobalVariable; + break; + case EOT_Rasterizer: + assert(!IsAnnotation); + assert(sizeof(SRasterizerGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SRasterizerGlobalVariable; + break; + case EOT_DepthStencil: + assert(!IsAnnotation); + assert(sizeof(SDepthStencilGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SDepthStencilGlobalVariable; + break; + case EOT_Sampler: + assert(!IsAnnotation); + assert(sizeof(SSamplerGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SSamplerGlobalVariable; + break; + case EOT_RenderTargetView: + assert(!IsAnnotation); + assert(sizeof(SRenderTargetViewGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SRenderTargetViewGlobalVariable; + break; + case EOT_DepthStencilView: + assert(!IsAnnotation); + assert(sizeof(SDepthStencilViewGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SDepthStencilViewGlobalVariable; + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid object type." ); + return E_FAIL; + break; + } + break; + case EVT_Numeric: + switch (pType->NumericType.NumericLayout) + { + case ENL_Matrix: + if (IsAnnotation) + { + assert(sizeof(SMatrixAnnotation) == sizeof(SAnnotation)); + new(pVar) SMatrixAnnotation; + } + else + { + assert(sizeof(SMatrixGlobalVariable) == sizeof(SGlobalVariable)); + assert(sizeof(SMatrix4x4ColumnMajorGlobalVariable) == sizeof(SGlobalVariable)); + assert(sizeof(SMatrix4x4RowMajorGlobalVariable) == sizeof(SGlobalVariable)); + + if (pType->NumericType.Rows == 4 && pType->NumericType.Columns == 4) + { + if (pType->NumericType.IsColumnMajor) + { + new(pVar) SMatrix4x4ColumnMajorGlobalVariable; + } + else + { + new(pVar) SMatrix4x4RowMajorGlobalVariable; + } + } + else + { + new(pVar) SMatrixGlobalVariable; + } + } + break; + case ENL_Vector: + switch (pType->NumericType.ScalarType) + { + case EST_Float: + if (IsAnnotation) + { + assert(sizeof(SFloatVectorAnnotation) == sizeof(SAnnotation)); + new(pVar) SFloatVectorAnnotation; + } + else + { + assert(sizeof(SFloatVectorGlobalVariable) == sizeof(SGlobalVariable)); + assert(sizeof(SFloatVector4GlobalVariable) == sizeof(SGlobalVariable)); + + if (pType->NumericType.Columns == 4) + { + new(pVar) SFloatVector4GlobalVariable; + } + else + { + new(pVar) SFloatVectorGlobalVariable; + } + } + break; + case EST_Bool: + if (IsAnnotation) + { + assert(sizeof(SBoolVectorAnnotation) == sizeof(SAnnotation)); + new(pVar) SBoolVectorAnnotation; + } + else + { + assert(sizeof(SBoolVectorGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SBoolVectorGlobalVariable; + } + break; + case EST_UInt: + case EST_Int: + if (IsAnnotation) + { + assert(sizeof(SIntVectorAnnotation) == sizeof(SAnnotation)); + new(pVar) SIntVectorAnnotation; + } + else + { + assert(sizeof(SIntVectorGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SIntVectorGlobalVariable; + } + break; + } + break; + case ENL_Scalar: + switch (pType->NumericType.ScalarType) + { + case EST_Float: + if (IsAnnotation) + { + assert(sizeof(SFloatScalarAnnotation) == sizeof(SAnnotation)); + new(pVar) SFloatScalarAnnotation; + } + else + { + assert(sizeof(SFloatScalarGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SFloatScalarGlobalVariable; + } + break; + case EST_UInt: + case EST_Int: + if (IsAnnotation) + { + assert(sizeof(SIntScalarAnnotation) == sizeof(SAnnotation)); + new(pVar) SIntScalarAnnotation; + } + else + { + assert(sizeof(SIntScalarGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SIntScalarGlobalVariable; + } + break; + case EST_Bool: + if (IsAnnotation) + { + assert(sizeof(SBoolScalarAnnotation) == sizeof(SAnnotation)); + new(pVar) SBoolScalarAnnotation; + } + else + { + assert(sizeof(SBoolScalarGlobalVariable) == sizeof(SGlobalVariable)); + new(pVar) SBoolScalarGlobalVariable; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid scalar type." ); + return E_FAIL; + break; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid numeric type." ); + return E_FAIL; + break; + } + break; + default: + assert(0); + DPF( 0, "Internal loading error: invalid variable type." ); + return E_FAIL; + break; + } + return S_OK; +} + +} |