featureSet.cpp
Engine/source/shaderGen/featureSet.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "shaderGen/featureSet.h" 26 27#include "shaderGen/featureType.h" 28#include "platform/profiler.h" 29#include "core/util/hashFunction.h" 30 31 32const FeatureSet FeatureSet::EmptySet; 33 34 35S32 QSORT_CALLBACK FeatureSet::_typeCmp( const FeatureInfo* a, const FeatureInfo* b ) 36{ 37 if ( a->type->getGroup() < b->type->getGroup() ) 38 return -1; 39 else if ( a->type->getGroup() > b->type->getGroup() ) 40 return 1; 41 else if ( a->index < b->index ) 42 return -1; 43 else if ( a->index > b->index ) 44 return 1; 45 else if ( a->type->getOrder() < b->type->getOrder() ) 46 return -1; 47 else if ( a->type->getOrder() > b->type->getOrder() ) 48 return 1; 49 else 50 return 0; 51} 52 53void FeatureSet::_rebuildDesc() 54{ 55 PROFILE_SCOPE( FeatureSet_RebuildDesc ); 56 57 // First get the features in the proper order. 58 mFeatures.sort( _typeCmp ); 59 60 String desc; 61 62 for ( U32 i=0; i < mFeatures.size(); i++ ) 63 desc += String::ToString( "%s,%d\n", 64 mFeatures[i].type->getName().c_str(), 65 mFeatures[i].index ); 66 67 // By interning the description we have only 68 // one instance in the system and we get fast 69 // pointer compares for equality. 70 mDescription = desc.intern(); 71} 72 73const FeatureType& FeatureSet::getAt( U32 index, S32 *outIndex ) const 74{ 75 // We want to make sure we access the features in the 76 // correct order. By asking for the description we ensure 77 // the feature set is properly sorted. 78 getDescription(); 79 80 if ( outIndex ) 81 *outIndex = mFeatures[index].index; 82 83 return *mFeatures[index].type; 84} 85 86void FeatureSet::clear() 87{ 88 mDescription.clear(); 89 mFeatures.clear(); 90} 91 92FeatureSet& FeatureSet::operator=( const FeatureSet &h ) 93{ 94 clear(); 95 merge( h ); 96 return *this; 97} 98 99bool FeatureSet::hasFeature( const FeatureType &type, S32 index ) const 100{ 101 PROFILE_SCOPE(FeatureSet_hasFeature); 102 103 for ( U32 i = 0; i < mFeatures.size(); i++) 104 { 105 if ( mFeatures[i].type == &type && 106 ( index < 0 || mFeatures[i].index == index ) ) 107 return true; 108 } 109 110 return false; 111} 112 113void FeatureSet::setFeature( const FeatureType &type, bool set, S32 index ) 114{ 115 for ( U32 i=0; i < mFeatures.size(); i++ ) 116 { 117 const FeatureInfo &info = mFeatures[i]; 118 if ( info.type == &type && info.index == index ) 119 { 120 if ( set ) 121 return; 122 else 123 { 124 mFeatures.erase_fast( i ); 125 mDescription.clear(); 126 return; 127 } 128 } 129 } 130 131 if ( !set ) 132 return; 133 134 FeatureInfo info; 135 info.type = &type; 136 info.index = index; 137 mFeatures.push_back( info ); 138 139 mDescription.clear(); 140} 141 142void FeatureSet::addFeature( const FeatureType &type, S32 index ) 143{ 144 for ( U32 i=0; i < mFeatures.size(); i++ ) 145 { 146 const FeatureInfo &info = mFeatures[i]; 147 if ( info.type == &type && 148 info.index == index ) 149 return; 150 } 151 152 FeatureInfo info; 153 info.type = &type; 154 info.index = index; 155 mFeatures.push_back( info ); 156 157 mDescription.clear(); 158} 159 160void FeatureSet::removeFeature( const FeatureType &type ) 161{ 162 for ( U32 i=0; i < mFeatures.size(); i++ ) 163 { 164 const FeatureInfo &info = mFeatures[i]; 165 if ( info.type == &type ) 166 { 167 mFeatures.erase_fast( i ); 168 mDescription.clear(); 169 return; 170 } 171 } 172} 173 174S32 FeatureSet::getNextFeatureIndex( const FeatureType &type, S32 index ) const 175{ 176 for ( U32 i=0; i < mFeatures.size(); i++ ) 177 { 178 const FeatureInfo &info = mFeatures[i]; 179 if ( info.type == &type && info.index > index ) 180 return i; 181 } 182 183 return -1; 184} 185 186void FeatureSet::filter( const FeatureSet &features ) 187{ 188 PROFILE_SCOPE( FeatureSet_Filter ); 189 190 for ( U32 i=0; i < mFeatures.size(); ) 191 { 192 if ( !features.hasFeature( *mFeatures[i].type ) ) 193 mFeatures.erase_fast( i ); 194 else 195 i++; 196 } 197 198 mDescription.clear(); 199} 200 201void FeatureSet::exclude( const FeatureSet &features ) 202{ 203 PROFILE_SCOPE( FeatureSet_Exclude ); 204 205 for ( U32 i=0; i < features.mFeatures.size(); i++ ) 206 removeFeature( *features.mFeatures[i].type ); 207 208 mDescription.clear(); 209} 210 211void FeatureSet::merge( const FeatureSet &features ) 212{ 213 PROFILE_SCOPE( FeatureSet_Merge ); 214 215 if ( mFeatures.empty() ) 216 { 217 mFeatures.merge( features.mFeatures ); 218 mDescription = features.mDescription; 219 return; 220 } 221 222 for ( U32 i=0; i < features.mFeatures.size(); i++ ) 223 addFeature( *features.mFeatures[i].type, 224 features.mFeatures[i].index ); 225} 226 227