storagesoa.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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       /*Type=*/arrayType,
00084       /*isConstant=*/false,
00085       /*Linkage=*/GlobalValue::ExternalLinkage,
00086       /*Initializer=*/0, // has initializer, specified below
00087       /*Name=*/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    //load->setAlignment(8);
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    //if we have an indirect index, always use that
00286    //   if not use the integer offset to create one
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       /*Type=*/IntegerType::get(32),
00384       /*isConstant=*/false,
00385       /*Linkage=*/GlobalValue::ExternalLinkage,
00386       /*Initializer=*/0, // has initializer, specified below
00387       /*Name=*/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 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4