170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com//
270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be
470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com// found in the LICENSE file.
570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com//
670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
9c7a4104957aa1f6fa36e4e9cf65d36b699eb05bdBrandon Jones#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
100b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
11c7a4104957aa1f6fa36e4e9cf65d36b699eb05bdBrandon Jones#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
120b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include "libGLESv2/ProgramBinary.h"
130b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include "libGLESv2/VertexAttribute.h"
1470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
1570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.comnamespace rx
1670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com{
1770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
1870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.comVertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
1970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com{
2070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
2170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
2270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        mVertexDeclCache[i].vertexDeclaration = NULL;
2370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        mVertexDeclCache[i].lruCount = 0;
2470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
2570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
2670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
2870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        mAppliedVBs[i].serial = 0;
2970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
3070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
3170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    mLastSetVDecl = NULL;
3270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    mInstancingEnabled = true;
3370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com}
3470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
3570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.comVertexDeclarationCache::~VertexDeclarationCache()
3670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com{
3770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
3870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
39ea2286352f5eba47dfaa3e9ab418bbacfd1ba8a1Geoff Lang        SafeRelease(mVertexDeclCache[i].vertexDeclaration);
4070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
4170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com}
4270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
43f7100b981f0856b238252e6052509eecf8e5adedGeoff Langgl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
4470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com{
4570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    *repeatDraw = 1;
4670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
4770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
4870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;
4970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
5009cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods    if (instances == 0)
5109cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods    {
5209cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
5309cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods        {
5409cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods            if (attributes[i].divisor != 0)
5509cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods            {
5609cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods                // If a divisor is set, it still applies even if an instanced draw was not used, so treat
5709cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods                // as a single-instance draw.
5809cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods                instances = 1;
5909cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods                break;
6009cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods            }
6109cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods        }
6209cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods    }
6309cf736b548787e9c766ac65b6366f9de2a690aeShannon Woods
6470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    if (instances > 0)
6570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
6670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        // Find an indexed attribute to be mapped to D3D stream 0
6770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
6870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        {
6970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            if (attributes[i].active)
7070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            {
7151817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0)
7270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                {
7351817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                    indexedAttribute = i;
7470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                }
7551817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0)
7670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                {
7751817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                    instancedAttribute = i;
7870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                }
7951817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS)
8051817d40f4d22606e62b1ad2c177a6b1e461b67fshannon.woods@transgaming.com                    break;   // Found both an indexed and instanced attribute
8170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            }
8270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        }
8370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
8487a93308da237626325d13339565d7136125ed0dGeoff Lang        // The validation layer checks that there is at least one active attribute with a zero divisor as per
8587a93308da237626325d13339565d7136125ed0dGeoff Lang        // the GL_ANGLE_instanced_arrays spec.
8687a93308da237626325d13339565d7136125ed0dGeoff Lang        ASSERT(indexedAttribute != gl::MAX_VERTEX_ATTRIBS);
8770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
8870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
8991fa9ce47649057c5b15113ea31c5ed4b7bd8fceGeoff Lang    D3DCAPS9 caps;
9091fa9ce47649057c5b15113ea31c5ed4b7bd8fceGeoff Lang    device->GetDeviceCaps(&caps);
9191fa9ce47649057c5b15113ea31c5ed4b7bd8fceGeoff Lang
9270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
9370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    D3DVERTEXELEMENT9 *element = &elements[0];
9470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
9570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
9670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
9770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        if (attributes[i].active)
9870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        {
99db1899ced07525c7efe27886ef131ab09bb5072ashannon.woods@transgaming.com            // Directly binding the storage buffer is not supported for d3d9
100db1899ced07525c7efe27886ef131ab09bb5072ashannon.woods@transgaming.com            ASSERT(attributes[i].storage == NULL);
101db1899ced07525c7efe27886ef131ab09bb5072ashannon.woods@transgaming.com
10270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            int stream = i;
10370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
10470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            if (instances > 0)
10570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            {
10670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
10770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
10870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                {
10970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    *repeatDraw = instances;
11070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                }
11170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                else
11270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                {
11370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    if (i == indexedAttribute)
11470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    {
11570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                        stream = 0;
11670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    }
11770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    else if (i == 0)
11870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    {
11970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                        stream = indexedAttribute;
12070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    }
12170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
12270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    UINT frequency = 1;
12370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
12470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    if (attributes[i].divisor == 0)
12570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    {
12670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
12770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    }
12870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    else
12970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    {
13070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
13170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    }
13270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
13370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    device->SetStreamSourceFreq(stream, frequency);
13470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                    mInstancingEnabled = true;
13570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                }
13670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            }
13770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
1384150d362e1d5f1e2cc4d63d171d1d72fb8be9cc7daniel@transgaming.com            VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer);
1394150d362e1d5f1e2cc4d63d171d1d72fb8be9cc7daniel@transgaming.com
14070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            if (mAppliedVBs[stream].serial != attributes[i].serial ||
14170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mAppliedVBs[stream].stride != attributes[i].stride ||
14270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mAppliedVBs[stream].offset != attributes[i].offset)
14370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            {
1444150d362e1d5f1e2cc4d63d171d1d72fb8be9cc7daniel@transgaming.com                device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
14570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mAppliedVBs[stream].serial = attributes[i].serial;
14670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mAppliedVBs[stream].stride = attributes[i].stride;
14770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mAppliedVBs[stream].offset = attributes[i].offset;
14870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            }
14970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
1508017787983621d5a2078ac04624b730a6374d314Jamie Madill            gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT);
15191fa9ce47649057c5b15113ea31c5ed4b7bd8fceGeoff Lang            const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat);
1528017787983621d5a2078ac04624b730a6374d314Jamie Madill
15370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element->Stream = stream;
15470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element->Offset = 0;
15591fa9ce47649057c5b15113ea31c5ed4b7bd8fceGeoff Lang            element->Type = d3d9VertexInfo.nativeFormat;
15670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element->Method = D3DDECLMETHOD_DEFAULT;
15770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element->Usage = D3DDECLUSAGE_TEXCOORD;
15870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element->UsageIndex = programBinary->getSemanticIndex(i);
15970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            element++;
16070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        }
16170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
16270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
16370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
16470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
16570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        if (mInstancingEnabled)
16670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        {
16770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
16870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            {
16970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                device->SetStreamSourceFreq(i, 1);
17070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            }
17170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
17270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            mInstancingEnabled = false;
17370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        }
17470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
17570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
17670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
17770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    *(element++) = end;
17870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
17970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
18070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
18170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
18270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
18370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        {
18470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            entry->lruCount = ++mMaxLru;
18570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            if(entry->vertexDeclaration != mLastSetVDecl)
18670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            {
18770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                device->SetVertexDeclaration(entry->vertexDeclaration);
18870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com                mLastSetVDecl = entry->vertexDeclaration;
18970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            }
19070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
191f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang            return gl::Error(GL_NO_ERROR);
19270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        }
19370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
19470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
19570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    VertexDeclCacheEntry *lastCache = mVertexDeclCache;
19670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
19770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
19870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
19970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
20070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        {
20170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com            lastCache = &mVertexDeclCache[i];
20270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        }
20370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
20470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
20570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    if (lastCache->vertexDeclaration != NULL)
20670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
207ea2286352f5eba47dfaa3e9ab418bbacfd1ba8a1Geoff Lang        SafeRelease(lastCache->vertexDeclaration);
20870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        // mLastSetVDecl is set to the replacement, so we don't have to worry
20970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        // about it.
21070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
21170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
21270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
213f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang    HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
214f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang    if (FAILED(result))
215f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang    {
216f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result);
217f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang    }
218f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang
21970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    device->SetVertexDeclaration(lastCache->vertexDeclaration);
22070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    mLastSetVDecl = lastCache->vertexDeclaration;
22170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    lastCache->lruCount = ++mMaxLru;
22270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
223f7100b981f0856b238252e6052509eecf8e5adedGeoff Lang    return gl::Error(GL_NO_ERROR);
22470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com}
22570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
22670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.comvoid VertexDeclarationCache::markStateDirty()
22770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com{
22870a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
22970a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    {
23070a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com        mAppliedVBs[i].serial = 0;
23170a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    }
23270a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
23370a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    mLastSetVDecl = NULL;
23470a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com    mInstancingEnabled = true;   // Forces it to be disabled when not used
23570a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com}
23670a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com
23770a219bc1637c98cae30baf60de6d713131a2755daniel@transgaming.com}
238