1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. 1.12 + 1.13 +#include "libGLESv2/ProgramBinary.h" 1.14 +#include "libGLESv2/Context.h" 1.15 +#include "libGLESv2/renderer/VertexBuffer9.h" 1.16 +#include "libGLESv2/renderer/VertexDeclarationCache.h" 1.17 + 1.18 +namespace rx 1.19 +{ 1.20 + 1.21 +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) 1.22 +{ 1.23 + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) 1.24 + { 1.25 + mVertexDeclCache[i].vertexDeclaration = NULL; 1.26 + mVertexDeclCache[i].lruCount = 0; 1.27 + } 1.28 + 1.29 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.30 + { 1.31 + mAppliedVBs[i].serial = 0; 1.32 + } 1.33 + 1.34 + mLastSetVDecl = NULL; 1.35 + mInstancingEnabled = true; 1.36 +} 1.37 + 1.38 +VertexDeclarationCache::~VertexDeclarationCache() 1.39 +{ 1.40 + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) 1.41 + { 1.42 + if (mVertexDeclCache[i].vertexDeclaration) 1.43 + { 1.44 + mVertexDeclCache[i].vertexDeclaration->Release(); 1.45 + } 1.46 + } 1.47 +} 1.48 + 1.49 +GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) 1.50 +{ 1.51 + *repeatDraw = 1; 1.52 + 1.53 + int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; 1.54 + int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; 1.55 + 1.56 + if (instances > 0) 1.57 + { 1.58 + // Find an indexed attribute to be mapped to D3D stream 0 1.59 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.60 + { 1.61 + if (attributes[i].active) 1.62 + { 1.63 + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) 1.64 + { 1.65 + indexedAttribute = i; 1.66 + } 1.67 + else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) 1.68 + { 1.69 + instancedAttribute = i; 1.70 + } 1.71 + if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) 1.72 + break; // Found both an indexed and instanced attribute 1.73 + } 1.74 + } 1.75 + 1.76 + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) 1.77 + { 1.78 + return GL_INVALID_OPERATION; 1.79 + } 1.80 + } 1.81 + 1.82 + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; 1.83 + D3DVERTEXELEMENT9 *element = &elements[0]; 1.84 + 1.85 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.86 + { 1.87 + if (attributes[i].active) 1.88 + { 1.89 + // Directly binding the storage buffer is not supported for d3d9 1.90 + ASSERT(attributes[i].storage == NULL); 1.91 + 1.92 + int stream = i; 1.93 + 1.94 + if (instances > 0) 1.95 + { 1.96 + // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. 1.97 + if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) 1.98 + { 1.99 + *repeatDraw = instances; 1.100 + } 1.101 + else 1.102 + { 1.103 + if (i == indexedAttribute) 1.104 + { 1.105 + stream = 0; 1.106 + } 1.107 + else if (i == 0) 1.108 + { 1.109 + stream = indexedAttribute; 1.110 + } 1.111 + 1.112 + UINT frequency = 1; 1.113 + 1.114 + if (attributes[i].divisor == 0) 1.115 + { 1.116 + frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; 1.117 + } 1.118 + else 1.119 + { 1.120 + frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; 1.121 + } 1.122 + 1.123 + device->SetStreamSourceFreq(stream, frequency); 1.124 + mInstancingEnabled = true; 1.125 + } 1.126 + } 1.127 + 1.128 + VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); 1.129 + 1.130 + if (mAppliedVBs[stream].serial != attributes[i].serial || 1.131 + mAppliedVBs[stream].stride != attributes[i].stride || 1.132 + mAppliedVBs[stream].offset != attributes[i].offset) 1.133 + { 1.134 + device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); 1.135 + mAppliedVBs[stream].serial = attributes[i].serial; 1.136 + mAppliedVBs[stream].stride = attributes[i].stride; 1.137 + mAppliedVBs[stream].offset = attributes[i].offset; 1.138 + } 1.139 + 1.140 + element->Stream = stream; 1.141 + element->Offset = 0; 1.142 + element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; 1.143 + element->Method = D3DDECLMETHOD_DEFAULT; 1.144 + element->Usage = D3DDECLUSAGE_TEXCOORD; 1.145 + element->UsageIndex = programBinary->getSemanticIndex(i); 1.146 + element++; 1.147 + } 1.148 + } 1.149 + 1.150 + if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) 1.151 + { 1.152 + if (mInstancingEnabled) 1.153 + { 1.154 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.155 + { 1.156 + device->SetStreamSourceFreq(i, 1); 1.157 + } 1.158 + 1.159 + mInstancingEnabled = false; 1.160 + } 1.161 + } 1.162 + 1.163 + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); 1.164 + *(element++) = end; 1.165 + 1.166 + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) 1.167 + { 1.168 + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; 1.169 + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) 1.170 + { 1.171 + entry->lruCount = ++mMaxLru; 1.172 + if(entry->vertexDeclaration != mLastSetVDecl) 1.173 + { 1.174 + device->SetVertexDeclaration(entry->vertexDeclaration); 1.175 + mLastSetVDecl = entry->vertexDeclaration; 1.176 + } 1.177 + 1.178 + return GL_NO_ERROR; 1.179 + } 1.180 + } 1.181 + 1.182 + VertexDeclCacheEntry *lastCache = mVertexDeclCache; 1.183 + 1.184 + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) 1.185 + { 1.186 + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) 1.187 + { 1.188 + lastCache = &mVertexDeclCache[i]; 1.189 + } 1.190 + } 1.191 + 1.192 + if (lastCache->vertexDeclaration != NULL) 1.193 + { 1.194 + lastCache->vertexDeclaration->Release(); 1.195 + lastCache->vertexDeclaration = NULL; 1.196 + // mLastSetVDecl is set to the replacement, so we don't have to worry 1.197 + // about it. 1.198 + } 1.199 + 1.200 + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); 1.201 + device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); 1.202 + device->SetVertexDeclaration(lastCache->vertexDeclaration); 1.203 + mLastSetVDecl = lastCache->vertexDeclaration; 1.204 + lastCache->lruCount = ++mMaxLru; 1.205 + 1.206 + return GL_NO_ERROR; 1.207 +} 1.208 + 1.209 +void VertexDeclarationCache::markStateDirty() 1.210 +{ 1.211 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.212 + { 1.213 + mAppliedVBs[i].serial = 0; 1.214 + } 1.215 + 1.216 + mLastSetVDecl = NULL; 1.217 + mInstancingEnabled = true; // Forces it to be disabled when not used 1.218 +} 1.219 + 1.220 +}