зеркало из https://github.com/microsoft/FX11.git
2989 строки
102 KiB
C++
2989 строки
102 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// 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.
|
|
//
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
//
|
|
// http://go.microsoft.com/fwlink/p/?LinkId=271568
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
#include "pchfx.h"
|
|
#include "SOParser.h"
|
|
|
|
namespace D3DX11Effects
|
|
{
|
|
|
|
extern SUnorderedAccessView g_NullUnorderedAccessView;
|
|
|
|
SBaseBlock::SBaseBlock() noexcept :
|
|
BlockType(EBT_Invalid),
|
|
IsUserManaged(false),
|
|
AssignmentCount(0),
|
|
pAssignments(nullptr)
|
|
{
|
|
}
|
|
|
|
SPassBlock::SPassBlock() noexcept :
|
|
BackingStore{},
|
|
pName(nullptr),
|
|
AnnotationCount(0),
|
|
pAnnotations(nullptr),
|
|
pEffect(nullptr),
|
|
InitiallyValid(true),
|
|
HasDependencies(false)
|
|
{
|
|
}
|
|
|
|
STechnique::STechnique() noexcept :
|
|
pName(nullptr),
|
|
PassCount(0),
|
|
pPasses(nullptr),
|
|
AnnotationCount(0),
|
|
pAnnotations(nullptr),
|
|
InitiallyValid( true ),
|
|
HasDependencies( false )
|
|
{
|
|
}
|
|
|
|
SGroup::SGroup() noexcept :
|
|
pName(nullptr),
|
|
TechniqueCount(0),
|
|
pTechniques(nullptr),
|
|
AnnotationCount(0),
|
|
pAnnotations(nullptr),
|
|
InitiallyValid( true ),
|
|
HasDependencies( false )
|
|
{
|
|
}
|
|
|
|
SDepthStencilBlock::SDepthStencilBlock() noexcept :
|
|
pDSObject(nullptr),
|
|
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() noexcept :
|
|
pBlendObject(nullptr),
|
|
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() noexcept :
|
|
pRasterizerObject(nullptr),
|
|
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() noexcept :
|
|
pD3DObject(nullptr),
|
|
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) noexcept :
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 ={};
|
|
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;
|
|
}
|
|
|
|
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 ) noexcept :
|
|
m_RefCount(1),
|
|
m_Flags(Flags),
|
|
m_pReflection(nullptr),
|
|
m_VariableCount(0),
|
|
m_pVariables(nullptr),
|
|
m_AnonymousShaderCount(0),
|
|
m_pAnonymousShaders(nullptr),
|
|
m_TechniqueCount(0),
|
|
m_GroupCount(0),
|
|
m_pGroups(nullptr),
|
|
m_pNullGroup(nullptr),
|
|
m_ShaderBlockCount(0),
|
|
m_pShaderBlocks(nullptr),
|
|
m_DepthStencilBlockCount(0),
|
|
m_pDepthStencilBlocks(nullptr),
|
|
m_BlendBlockCount(0),
|
|
m_pBlendBlocks(nullptr),
|
|
m_RasterizerBlockCount(0),
|
|
m_pRasterizerBlocks(nullptr),
|
|
m_SamplerBlockCount(0),
|
|
m_pSamplerBlocks(nullptr),
|
|
m_MemberDataCount(0),
|
|
m_pMemberDataBlocks(nullptr),
|
|
m_InterfaceCount(0),
|
|
m_pInterfaces(nullptr),
|
|
m_CBCount(0),
|
|
m_pCBs(nullptr),
|
|
m_StringCount(0),
|
|
m_pStrings(nullptr),
|
|
m_ShaderResourceCount(0),
|
|
m_pShaderResources(nullptr),
|
|
m_UnorderedAccessViewCount(0),
|
|
m_pUnorderedAccessViews(nullptr),
|
|
m_RenderTargetViewCount(0),
|
|
m_pRenderTargetViews(nullptr),
|
|
m_DepthStencilViewCount(0),
|
|
m_pDepthStencilViews(nullptr),
|
|
m_LocalTimer(1),
|
|
m_FXLIndex(0),
|
|
m_pDevice(nullptr),
|
|
m_pContext(nullptr),
|
|
m_pClassLinkage(nullptr),
|
|
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;
|
|
|
|
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
|
|
if (m_pCBs)
|
|
{
|
|
assert(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 (size_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, static_cast<UINT>(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;
|
|
}
|
|
|
|
}
|