00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "storagesoa.h"
00029
00030 #include "gallivm_p.h"
00031
00032 #include "pipe/p_shader_tokens.h"
00033 #include "pipe/p_debug.h"
00034
00035 #include <llvm/BasicBlock.h>
00036 #include <llvm/Module.h>
00037 #include <llvm/Value.h>
00038
00039 #include <llvm/CallingConv.h>
00040 #include <llvm/Constants.h>
00041 #include <llvm/DerivedTypes.h>
00042 #include <llvm/InstrTypes.h>
00043 #include <llvm/Instructions.h>
00044
00045 using namespace llvm;
00046
00047
00048 StorageSoa::StorageSoa(llvm::BasicBlock *block,
00049 llvm::Value *input,
00050 llvm::Value *output,
00051 llvm::Value *consts,
00052 llvm::Value *temps)
00053 : m_block(block),
00054 m_input(input),
00055 m_output(output),
00056 m_consts(consts),
00057 m_temps(temps),
00058 m_immediates(0),
00059 m_idx(0)
00060 {
00061 }
00062
00063 void StorageSoa::addImmediate(float *vec)
00064 {
00065 std::vector<float> vals(4);
00066 vals[0] = vec[0];
00067 vals[1] = vec[1];
00068 vals[2] = vec[2];
00069 vals[3] = vec[3];
00070 m_immediatesToFlush.push_back(vals);
00071 }
00072
00073 void StorageSoa::declareImmediates()
00074 {
00075 if (m_immediatesToFlush.empty())
00076 return;
00077
00078 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
00079 ArrayType *vectorChannels = ArrayType::get(vectorType, 4);
00080 ArrayType *arrayType = ArrayType::get(vectorChannels, m_immediatesToFlush.size());
00081
00082 m_immediates = new GlobalVariable(
00083 arrayType,
00084 false,
00085 GlobalValue::ExternalLinkage,
00086 0,
00087 name("immediates"),
00088 currentModule());
00089
00090 std::vector<Constant*> arrayVals;
00091 for (unsigned int i = 0; i < m_immediatesToFlush.size(); ++i) {
00092 std::vector<float> vec = m_immediatesToFlush[i];
00093 std::vector<float> vals(4);
00094 std::vector<Constant*> channelArray;
00095
00096 vals[0] = vec[0]; vals[1] = vec[0]; vals[2] = vec[0]; vals[3] = vec[0];
00097 llvm::Constant *xChannel = createConstGlobalVector(vals);
00098
00099 vals[0] = vec[1]; vals[1] = vec[1]; vals[2] = vec[1]; vals[3] = vec[1];
00100 llvm::Constant *yChannel = createConstGlobalVector(vals);
00101
00102 vals[0] = vec[2]; vals[1] = vec[2]; vals[2] = vec[2]; vals[3] = vec[2];
00103 llvm::Constant *zChannel = createConstGlobalVector(vals);
00104
00105 vals[0] = vec[3]; vals[1] = vec[3]; vals[2] = vec[3]; vals[3] = vec[3];
00106 llvm::Constant *wChannel = createConstGlobalVector(vals);
00107 channelArray.push_back(xChannel);
00108 channelArray.push_back(yChannel);
00109 channelArray.push_back(zChannel);
00110 channelArray.push_back(wChannel);
00111 Constant *constChannels = ConstantArray::get(vectorChannels,
00112 channelArray);
00113 arrayVals.push_back(constChannels);
00114 }
00115 Constant *constArray = ConstantArray::get(arrayType, arrayVals);
00116 m_immediates->setInitializer(constArray);
00117
00118 m_immediatesToFlush.clear();
00119 }
00120
00121 llvm::Value *StorageSoa::addrElement(int idx) const
00122 {
00123 std::map<int, llvm::Value*>::const_iterator itr = m_addresses.find(idx);
00124 if (itr == m_addresses.end()) {
00125 debug_printf("Trying to access invalid shader 'address'\n");
00126 return 0;
00127 }
00128 llvm::Value * res = (*itr).second;
00129
00130 res = new LoadInst(res, name("addr"), false, m_block);
00131
00132 return res;
00133 }
00134
00135 std::vector<llvm::Value*> StorageSoa::inputElement(llvm::Value *idx)
00136 {
00137 std::vector<llvm::Value*> res(4);
00138
00139 res[0] = element(m_input, idx, 0);
00140 res[1] = element(m_input, idx, 1);
00141 res[2] = element(m_input, idx, 2);
00142 res[3] = element(m_input, idx, 3);
00143
00144 return res;
00145 }
00146
00147 std::vector<llvm::Value*> StorageSoa::constElement(llvm::Value *idx)
00148 {
00149 std::vector<llvm::Value*> res(4);
00150 llvm::Value *xChannel, *yChannel, *zChannel, *wChannel;
00151
00152 xChannel = elementPointer(m_consts, idx, 0);
00153 yChannel = elementPointer(m_consts, idx, 1);
00154 zChannel = elementPointer(m_consts, idx, 2);
00155 wChannel = elementPointer(m_consts, idx, 3);
00156
00157 res[0] = alignedArrayLoad(xChannel);
00158 res[1] = alignedArrayLoad(yChannel);
00159 res[2] = alignedArrayLoad(zChannel);
00160 res[3] = alignedArrayLoad(wChannel);
00161
00162 return res;
00163 }
00164
00165 std::vector<llvm::Value*> StorageSoa::outputElement(llvm::Value *idx)
00166 {
00167 std::vector<llvm::Value*> res(4);
00168
00169 res[0] = element(m_output, idx, 0);
00170 res[1] = element(m_output, idx, 1);
00171 res[2] = element(m_output, idx, 2);
00172 res[3] = element(m_output, idx, 3);
00173
00174 return res;
00175 }
00176
00177 std::vector<llvm::Value*> StorageSoa::tempElement(llvm::Value *idx)
00178 {
00179 std::vector<llvm::Value*> res(4);
00180
00181 res[0] = element(m_temps, idx, 0);
00182 res[1] = element(m_temps, idx, 1);
00183 res[2] = element(m_temps, idx, 2);
00184 res[3] = element(m_temps, idx, 3);
00185
00186 return res;
00187 }
00188
00189 std::vector<llvm::Value*> StorageSoa::immediateElement(llvm::Value *idx)
00190 {
00191 std::vector<llvm::Value*> res(4);
00192
00193 res[0] = element(m_immediates, idx, 0);
00194 res[1] = element(m_immediates, idx, 1);
00195 res[2] = element(m_immediates, idx, 2);
00196 res[3] = element(m_immediates, idx, 3);
00197
00198 return res;
00199 }
00200
00201 llvm::Value * StorageSoa::elementPointer(llvm::Value *ptr, llvm::Value *index,
00202 int channel) const
00203 {
00204 std::vector<Value*> indices;
00205 if (m_immediates == ptr)
00206 indices.push_back(constantInt(0));
00207 indices.push_back(index);
00208 indices.push_back(constantInt(channel));
00209
00210 GetElementPtrInst *getElem = GetElementPtrInst::Create(ptr,
00211 indices.begin(),
00212 indices.end(),
00213 name("ptr"),
00214 m_block);
00215 return getElem;
00216 }
00217
00218 llvm::Value * StorageSoa::element(llvm::Value *ptr, llvm::Value *index,
00219 int channel) const
00220 {
00221 llvm::Value *res = elementPointer(ptr, index, channel);
00222 LoadInst *load = new LoadInst(res, name("element"), false, m_block);
00223
00224 return load;
00225 }
00226
00227 const char * StorageSoa::name(const char *prefix) const
00228 {
00229 ++m_idx;
00230 snprintf(m_name, 32, "%s%d", prefix, m_idx);
00231 return m_name;
00232 }
00233
00234 llvm::ConstantInt * StorageSoa::constantInt(int idx) const
00235 {
00236 if (m_constInts.find(idx) != m_constInts.end()) {
00237 return m_constInts[idx];
00238 }
00239 ConstantInt *constInt = ConstantInt::get(APInt(32, idx));
00240 m_constInts[idx] = constInt;
00241 return constInt;
00242 }
00243
00244 llvm::Value *StorageSoa::alignedArrayLoad(llvm::Value *val)
00245 {
00246 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
00247 PointerType *vectorPtr = PointerType::get(vectorType, 0);
00248
00249 CastInst *cast = new BitCastInst(val, vectorPtr, name("toVector"), m_block);
00250 LoadInst *load = new LoadInst(cast, name("alignLoad"), false, m_block);
00251 load->setAlignment(8);
00252 return load;
00253 }
00254
00255 llvm::Module * StorageSoa::currentModule() const
00256 {
00257 if (!m_block || !m_block->getParent())
00258 return 0;
00259
00260 return m_block->getParent()->getParent();
00261 }
00262
00263 llvm::Constant * StorageSoa::createConstGlobalVector(const std::vector<float> &vec)
00264 {
00265 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
00266 std::vector<Constant*> immValues;
00267 ConstantFP *constx = ConstantFP::get(APFloat(vec[0]));
00268 ConstantFP *consty = ConstantFP::get(APFloat(vec[1]));
00269 ConstantFP *constz = ConstantFP::get(APFloat(vec[2]));
00270 ConstantFP *constw = ConstantFP::get(APFloat(vec[3]));
00271 immValues.push_back(constx);
00272 immValues.push_back(consty);
00273 immValues.push_back(constz);
00274 immValues.push_back(constw);
00275 Constant *constVector = ConstantVector::get(vectorType, immValues);
00276
00277 return constVector;
00278 }
00279
00280 std::vector<llvm::Value*> StorageSoa::load(enum tgsi_file_type type, int idx, int swizzle,
00281 llvm::Value *indIdx)
00282 {
00283 std::vector<llvm::Value*> val(4);
00284
00285
00286
00287 llvm::Value *realIndex = 0;
00288 if (indIdx)
00289 realIndex = indIdx;
00290 else
00291 realIndex = constantInt(idx);
00292 debug_printf("XXXXXXXXX realIdx = %p, indIdx = %p\n", realIndex, indIdx);
00293
00294 switch(type) {
00295 case TGSI_FILE_INPUT:
00296 val = inputElement(realIndex);
00297 break;
00298 case TGSI_FILE_OUTPUT:
00299 val = outputElement(realIndex);
00300 break;
00301 case TGSI_FILE_TEMPORARY:
00302 val = tempElement(realIndex);
00303 break;
00304 case TGSI_FILE_CONSTANT:
00305 val = constElement(realIndex);
00306 break;
00307 case TGSI_FILE_IMMEDIATE:
00308 val = immediateElement(realIndex);
00309 break;
00310 case TGSI_FILE_ADDRESS:
00311 debug_printf("Address not handled in the load phase!\n");
00312 assert(0);
00313 break;
00314 default:
00315 debug_printf("Unknown load!\n");
00316 assert(0);
00317 break;
00318 }
00319 if (!gallivm_is_swizzle(swizzle))
00320 return val;
00321
00322 std::vector<llvm::Value*> res(4);
00323
00324 res[0] = val[gallivm_x_swizzle(swizzle)];
00325 res[1] = val[gallivm_y_swizzle(swizzle)];
00326 res[2] = val[gallivm_z_swizzle(swizzle)];
00327 res[3] = val[gallivm_w_swizzle(swizzle)];
00328 return res;
00329 }
00330
00331 void StorageSoa::store(enum tgsi_file_type type, int idx, const std::vector<llvm::Value*> &val,
00332 int mask)
00333 {
00334 llvm::Value *out = 0;
00335 switch(type) {
00336 case TGSI_FILE_OUTPUT:
00337 out = m_output;
00338 break;
00339 case TGSI_FILE_TEMPORARY:
00340 out = m_temps;
00341 break;
00342 case TGSI_FILE_INPUT:
00343 out = m_input;
00344 break;
00345 case TGSI_FILE_ADDRESS: {
00346 llvm::Value *addr = m_addresses[idx];
00347 if (!addr) {
00348 addAddress(idx);
00349 addr = m_addresses[idx];
00350 assert(addr);
00351 }
00352 new StoreInst(val[0], addr, false, m_block);
00353 return;
00354 break;
00355 }
00356 default:
00357 debug_printf("Can't save output of this type: %d !\n", type);
00358 assert(0);
00359 break;
00360 }
00361 llvm::Value *realIndex = constantInt(idx);
00362 if ((mask & TGSI_WRITEMASK_X)) {
00363 llvm::Value *xChannel = elementPointer(out, realIndex, 0);
00364 new StoreInst(val[0], xChannel, false, m_block);
00365 }
00366 if ((mask & TGSI_WRITEMASK_Y)) {
00367 llvm::Value *yChannel = elementPointer(out, realIndex, 1);
00368 new StoreInst(val[1], yChannel, false, m_block);
00369 }
00370 if ((mask & TGSI_WRITEMASK_Z)) {
00371 llvm::Value *zChannel = elementPointer(out, realIndex, 2);
00372 new StoreInst(val[2], zChannel, false, m_block);
00373 }
00374 if ((mask & TGSI_WRITEMASK_W)) {
00375 llvm::Value *wChannel = elementPointer(out, realIndex, 3);
00376 new StoreInst(val[3], wChannel, false, m_block);
00377 }
00378 }
00379
00380 void StorageSoa::addAddress(int idx)
00381 {
00382 GlobalVariable *val = new GlobalVariable(
00383 IntegerType::get(32),
00384 false,
00385 GlobalValue::ExternalLinkage,
00386 0,
00387 name("address"),
00388 currentModule());
00389 val->setInitializer(Constant::getNullValue(IntegerType::get(32)));
00390
00391 debug_printf("adding to %d\n", idx);
00392 m_addresses[idx] = val;
00393 }