Skip to content
Permalink
Browse files
Make input layout cache stop using strings (from dev branch)
Load time: 2.54s -> 2.03s
  • Loading branch information
rygorous committed Mar 4, 2013
1 parent 574e48e commit b109933
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
@@ -24,7 +24,7 @@ CPUTInputLayoutCacheDX11* CPUTInputLayoutCacheDX11::mpInputLayoutCache = NULL;
void CPUTInputLayoutCacheDX11::ClearLayoutCache()
{
// iterate over the entire map - and release each layout object
std::map<cString, ID3D11InputLayout*>::iterator mapIterator;
std::map<LayoutKey, ID3D11InputLayout*>::iterator mapIterator;

for(mapIterator = mLayoutList.begin(); mapIterator != mLayoutList.end(); mapIterator++)
{
@@ -64,12 +64,8 @@ CPUTResult CPUTInputLayoutCacheDX11::GetLayout(
CPUTVertexShaderDX11 *pVertexShader,
ID3D11InputLayout **ppInputLayout
){
// Generate the vertex layout pattern portion of the key
cString layoutKey = GenerateLayoutKey(pDXLayout);

// Append the vertex shader pointer to the key for layout<->vertex shader relationship
cString address = ptoc(pVertexShader);
layoutKey += address;
// Generate the vertex layout key
LayoutKey layoutKey(pDXLayout, pVertexShader, true);

// Do we already have one like this?
if( mLayoutList[layoutKey] )
@@ -102,28 +98,58 @@ CPUTResult CPUTInputLayoutCacheDX11::GetLayout(
return CPUT_SUCCESS;
}

// Generate a string version of the vertex-buffer's layout. Allows us to search, compare, etc...
//-----------------------------------------------------------------------------
cString CPUTInputLayoutCacheDX11::GenerateLayoutKey(D3D11_INPUT_ELEMENT_DESC *pDXLayout)
CPUTInputLayoutCacheDX11::LayoutKey::LayoutKey()
: layout(NULL), vs(NULL), nElems(0), layout_owned(false)
{
// TODO: Duh! We can simply memcmp the DX layouts == use the layout input description directly as the key.
// We just need to know how many elements, or NULL terminate it.
// Uses less memory, faster, etc...
// Duh!
}

if( !pDXLayout[0].SemanticName )
{
return _L("");
}
// TODO: Use shorter names, etc...
ASSERT( (pDXLayout[0].Format>=0) && (pDXLayout[0].Format<=DXGI_FORMAT_BC7_UNORM_SRGB), _L("Invalid DXGI Format.") );
// Start first layout entry and no comma.
cString layoutKey = s2ws(pDXLayout[0].SemanticName) + _L(":") + gpDXGIFormatNames[pDXLayout[0].Format];
for( int index=1; NULL != pDXLayout[index].SemanticName; index++ )
{
ASSERT( (pDXLayout[index].Format>=0) && (pDXLayout[index].Format<=DXGI_FORMAT_BC7_UNORM_SRGB), _L("Invalid DXGI Format.") );
// Add a comma and the next layout entry
layoutKey = layoutKey + _L(",") + s2ws(pDXLayout[index].SemanticName) + _L(":") + gpDXGIFormatNames[pDXLayout[index].Format];
}
return layoutKey;
CPUTInputLayoutCacheDX11::LayoutKey::LayoutKey(const D3D11_INPUT_ELEMENT_DESC *pDXLayout, void *vs, bool just_ref)
{
nElems = 0;
while (pDXLayout[nElems].SemanticName)
++nElems;

if (just_ref)
{
layout = pDXLayout;
this->vs = vs;
layout_owned = false;
}
else
{
D3D11_INPUT_ELEMENT_DESC *copy = new D3D11_INPUT_ELEMENT_DESC[nElems];
memcpy(copy, pDXLayout, nElems * sizeof(*copy));
layout = copy;
this->vs = vs;
layout_owned = true;
}
}

CPUTInputLayoutCacheDX11::LayoutKey::LayoutKey(const LayoutKey &x)
{
D3D11_INPUT_ELEMENT_DESC *copy = new D3D11_INPUT_ELEMENT_DESC[x.nElems];
memcpy(copy, x.layout, x.nElems * sizeof(*copy));
layout = copy;
vs = x.vs;
nElems = x.nElems;
layout_owned = true;
}

CPUTInputLayoutCacheDX11::LayoutKey::~LayoutKey()
{
if (layout_owned)
{
SAFE_DELETE_ARRAY(layout);
}
}

CPUTInputLayoutCacheDX11::LayoutKey &CPUTInputLayoutCacheDX11::LayoutKey::operator =(const LayoutKey &x)
{
LayoutKey copy(x);
std::swap(layout, copy.layout);
std::swap(vs, copy.vs);
std::swap(nElems, copy.nElems);
std::swap(layout_owned, copy.layout_owned);
return *this;
}
@@ -35,16 +35,39 @@ class CPUTInputLayoutCacheDX11:public CPUTInputLayoutCache
void ClearLayoutCache();

private:
struct LayoutKey
{
const D3D11_INPUT_ELEMENT_DESC *layout;
void *vs;
int nElems;
bool layout_owned;

LayoutKey();
LayoutKey(const D3D11_INPUT_ELEMENT_DESC *pDXLayout, void *vs, bool just_ref);
LayoutKey(const LayoutKey &x);
~LayoutKey();

LayoutKey& operator =(const LayoutKey &x);

inline bool operator <(const LayoutKey &x) const
{
if (vs != x.vs)
return vs < x.vs;

if (nElems != x.nElems)
return nElems < x.nElems;

return memcmp(layout, x.layout, sizeof(*layout) * nElems) < 0;
}
};

// singleton
CPUTInputLayoutCacheDX11() { mLayoutList.clear(); }

// convert the D3D11_INPUT_ELEMENT_DESC to string key
cString GenerateLayoutKey(D3D11_INPUT_ELEMENT_DESC *pDXLayout);

CPUTResult VerifyLayoutCompatibility(D3D11_INPUT_ELEMENT_DESC *pDXLayout, ID3DBlob *pVertexShaderBlob);

static CPUTInputLayoutCacheDX11 *mpInputLayoutCache;
std::map<cString, ID3D11InputLayout*> mLayoutList;
std::map<LayoutKey, ID3D11InputLayout*> mLayoutList;
};

#endif //#define __CPUTINPUTLAYOUTCACHERDX11_H__

0 comments on commit b109933

Please sign in to comment.