コード例 #1
0
ファイル: VarianceShadowRenderer.cpp プロジェクト: gan74/n
void VarianceShadowRenderer::render(void *ptr) {
	child->render(ptr);

	getFrameBuffer().bind();
	ShaderInstance *sh = getVSMShader();
	sh->setValue(SVTexture0, child->getShadowMap());
	sh->bind();
	GLContext::getContext()->getScreen().draw(MaterialRenderData());

	FrameBuffer *temp = GLContext::getContext()->getFrameBufferPool().get(getSize(), false, ImageFormat::RG32F);
	blurs[1]->setValue(SVTexture0, temp->getAttachment(0));
	blurs[0]->setValue(SVTexture0, getFrameBuffer().getAttachment(0));

	temp->bind();
	blurs[0]->bind();
	GLContext::getContext()->getScreen().draw(MaterialRenderData());

	getFrameBuffer().bind();
	blurs[1]->bind();
	GLContext::getContext()->getScreen().draw(MaterialRenderData());

	blurs[1]->unbind();
	GLContext::getContext()->getFrameBufferPool().add(temp);
	child->discardBuffer();
}
コード例 #2
0
//-------------------------------------------------------------------------
// @brief 
//-------------------------------------------------------------------------
const ShaderInstance ForceField::deserialise( const tinyxml2::XMLElement* element)
{
    ShaderInstance shaderInstance;
    
    const tinyxml2::XMLAttribute* attribute = element->FindAttribute("name");
    if (attribute != nullptr)
    {
        m_name = attribute->Value();
    }

    for (element = element->FirstChildElement(); element != 0; element = element->NextSiblingElement())
    {
        unsigned int typeHash = hashString(element->Value());
        if (Material::m_hash == typeHash)
        {
            shaderInstance.getMaterial().deserialise(m_resource, getGameResource().getDeviceManager(), getGameResource().getTextureManager(), getGameResource().getLightManager(), element);
            shaderInstance.getMaterial().setBlendState(true);
        }
        else if (Vector3::m_hash == typeHash)
        {
            m_position.deserialise(element);
            translate(m_world, m_position.x(), m_position.y(), m_position.z());
        }
    }

    return shaderInstance;
}
コード例 #3
0
//-------------------------------------------------------------------------
// @brief 
//-------------------------------------------------------------------------
const ShaderInstance Core::deserialise( const tinyxml2::XMLElement* element)
{
    ShaderInstance shaderInstance;
    
    const tinyxml2::XMLAttribute* attribute = element->FindAttribute("name");
    if (attribute != nullptr)
    {
        m_name = attribute->Value();
    }

    for (const tinyxml2::XMLElement* childElement = element->FirstChildElement(); childElement; childElement = childElement->NextSiblingElement())
    {
        unsigned int childElementHash = hashString(childElement->Value());
        if (childElementHash == Material::m_hash)
        {
            const tinyxml2::XMLAttribute* nameAttribute = childElement->FindAttribute("name"); //This material needs a name to distinguish between normal and glowing versions of the material
            if (nameAttribute)
            {
                if (strICmp(nameAttribute->Value(), "CoreMaterialNormal"))
                {
                    m_forcefieldmatnormal.deserialise(m_resource, getGameResource().getDeviceManager(), getGameResource().getTextureManager(), getGameResource().getLightManager(), childElement);
                    shaderInstance.getMaterial().deserialise(m_resource, getGameResource().getDeviceManager(), getGameResource().getTextureManager(), getGameResource().getLightManager(), childElement);
                    shaderInstance.getMaterial().addTextureReference(Material::TextureSlotMapping(hashString("cube_player_forcefield"), Material::TextureSlotMapping::Diffuse0));
                }
                else if( strICmp(nameAttribute->Value(), "CoreMaterialNormalGlow") )
                {
                    m_forcefieldmatglowing.deserialise(m_resource, getGameResource().getDeviceManager(), getGameResource().getTextureManager(), getGameResource().getLightManager(), childElement);
                }
            }
        }
        else if (childElementHash == hashString("Model"))
        {
            attribute = childElement->FindAttribute("file_name");
            if (attribute != nullptr)
            {
                //Heavily relies on the shader instance existing before we load the model, might be better to put the model construction in initialise instead
                m_drawableObject = getWriteableGameResource().getModelManager().LoadModel(m_resource, shaderInstance, attribute->Value());
                m_drawableObject->setDirty();
            }
        }
    }

    //Get texture strings and load textures
    const SettingsManager& sm = getGameResource().getSettingsManager();
    TextureManager& tm = getWriteableGameResource().getTextureManager();
    const ISetting<std::string>* textureString = sm.getSetting<std::string>("Core");
    if (textureString)
    {
        tm.addLoad(getGameResource().getDeviceManager(), textureString->getData());
        shaderInstance.getMaterial().addTextureReference(Material::TextureSlotMapping(hashString(getTextureNameFromFileName(textureString->getData())), Material::TextureSlotMapping::Diffuse0));
    }
    textureString = sm.getSetting<std::string>("ForceFieldCore");
    if (textureString)
    {
        tm.addLoad(getGameResource().getDeviceManager(), textureString->getData());
        shaderInstance.getMaterial().addTextureReference(Material::TextureSlotMapping(hashString(getTextureNameFromFileName(textureString->getData())), Material::TextureSlotMapping::Diffuse0));
    }

    return shaderInstance;
}
コード例 #4
0
void GunTurret::fireLaser()
{
    ShaderInstance shaderInstance;
    shaderInstance.setMaterial(Material(0.0f, Color::black(), Color::black(), Color::red(), Color::red()));
    shaderInstance.getMaterial().setBlendState(true);
    shaderInstance.getMaterial().setEffect(getGameResource().getEffectCache().getEffect("laser_effect.xml"));

    getWriteableGameResource().getLaserManager().addInstance(m_position + Vector3(0.0f, 3.0f, 0.0f), m_direction, shaderInstance);
}
コード例 #5
0
//-------------------------------------------------------------------------
// @brief 
//-------------------------------------------------------------------------
const ShaderInstance GunTurret::deserialise( const tinyxml2::XMLElement* element)
{
    ShaderInstance shaderInstance;
    const tinyxml2::XMLAttribute* attribute = element->FindAttribute("name");
    if (attribute != nullptr)
    {
        m_name = attribute->Value();
    }

    Matrix44 scaleTransform, translation, rotation;
    for (const tinyxml2::XMLElement* childElement = element->FirstChildElement(); childElement; childElement = childElement->NextSiblingElement())
    {
        unsigned int childElementHash = hashString(childElement->Value());
        if (childElementHash == Vector3::m_hash)
        {
            const tinyxml2::XMLAttribute* nameAttribute = childElement->FindAttribute("name"); //This material needs a name to distinguish between normal and glowing versions of the material
            if (nameAttribute)
            {
                if (strICmp(nameAttribute->Value(), "position"))
                {
                    m_position.deserialise(childElement);
                    
                    scale(scaleTransform, 5.0f, 5.0f, 5.0f);
                    translate(translation, m_position);  
                }
                else if( strICmp(nameAttribute->Value(), "direction") )
                {
                    m_direction.deserialise(childElement);
                    m_direction.normalize();
                    rotation = rotationFromDirection(m_direction);
                }
            }
        }
        if (childElementHash == hashString("Model"))
        {
            attribute = childElement->FindAttribute("file");
            if (attribute != nullptr)
            {
                //Heavily relies on the shader instance existing before we load the model, might be better to put the model construction in initialise instead
                m_drawableObject = getWriteableGameResource().getModelManager().LoadModel(m_resource, shaderInstance, attribute->Value());
                m_drawableObject->setDirty();
            }
        }
        if (childElementHash == Material::m_hash)
        {
            shaderInstance.getMaterial().deserialise(m_resource, getGameResource().getDeviceManager(), getGameResource().getTextureManager(), getGameResource().getLightManager(), childElement );
        }
    }

    m_world = rotation * scaleTransform * translation;

    return shaderInstance;
}
コード例 #6
0
llvm::Type *
BackendLLVM::llvm_type_groupdata ()
{
    // If already computed, return it
    if (m_llvm_type_groupdata)
        return m_llvm_type_groupdata;

    std::vector<llvm::Type*> fields;

    // First, add the array that tells if each layer has run.  But only make
    // slots for the layers that may be called/used.
    int sz = (m_num_used_layers + 3) & (~3);  // Round up to 32 bit boundary
    fields.push_back (ll.type_array (ll.type_bool(), sz));
    size_t offset = sz * sizeof(bool);

    // For each layer in the group, add entries for all params that are
    // connected or interpolated, and output params.  Also mark those
    // symbols with their offset within the group struct.
    if (llvm_debug() >= 2)
        std::cout << "Group param struct:\n";
    m_param_order_map.clear ();
    int order = 1;
    for (int layer = 0;  layer < group().nlayers();  ++layer) {
        ShaderInstance *inst = group()[layer];
        if (inst->unused())
            continue;
        FOREACH_PARAM (Symbol &sym, inst) {
            TypeSpec ts = sym.typespec();
            if (ts.is_structure())  // skip the struct symbol itself
                continue;
            int arraylen = std::max (1, sym.typespec().arraylength());
            int deriv_mult = sym.has_derivs() ? 3 : 1;
            int n = arraylen * deriv_mult;
            ts.make_array (n);
            fields.push_back (llvm_type (ts));

            // Alignment
            size_t align = sym.typespec().is_closure_based() ? sizeof(void*) :
                    sym.typespec().simpletype().basesize();
            if (offset & (align-1))
                offset += align - (offset & (align-1));
            if (llvm_debug() >= 2)
                std::cout << "  " << inst->layername() 
                          << " (" << inst->id() << ") " << sym.mangled()
                          << " " << ts.c_str() << ", field " << order 
                          << ", offset " << offset << std::endl;
            sym.dataoffset ((int)offset);
            offset += int(sym.size()) * deriv_mult;

            m_param_order_map[&sym] = order;
            ++order;
        }
    }
コード例 #7
0
bool
ShaderInstance::mergeable (const ShaderInstance &b, const ShaderGroup &g) const
{
    // Must both be instances of the same master -- very fast early-out
    // for most potential pair comparisons.
    if (master() != b.master())
        return false;

    // If the shaders haven't been optimized yet, they don't yet have
    // their own symbol tables and instructions (they just refer to
    // their unoptimized master), but they may have an "instance
    // override" vector that describes which parameters have
    // instance-specific values or connections.
    bool optimized = (m_instsymbols.size() != 0 || m_instops.size() != 0);

    // Same instance overrides
    if (m_instoverrides.size() || b.m_instoverrides.size()) {
        ASSERT (! optimized);  // should not be post-opt
        ASSERT (m_instoverrides.size() == b.m_instoverrides.size());
        for (size_t i = 0, e = m_instoverrides.size();  i < e;  ++i) {
            if ((m_instoverrides[i].valuesource() == Symbol::DefaultVal ||
                 m_instoverrides[i].valuesource() == Symbol::InstanceVal) &&
                (b.m_instoverrides[i].valuesource() == Symbol::DefaultVal ||
                 b.m_instoverrides[i].valuesource() == Symbol::InstanceVal)) {
                // If both params are defaults or instances, let the
                // instance parameter value checking below handle
                // things. No need to reject default-vs-instance
                // mismatches if the actual values turn out to be the
                // same later.
                continue;
            }

            if (! (equivalent(m_instoverrides[i], b.m_instoverrides[i]))) {
                const Symbol *sym = mastersymbol(i);  // remember, it's pre-opt
                if (! sym->everused())
                    continue;
                return false;
            }
        }
    }

    // Make sure that the two nodes have the same parameter values.  If
    // the group has already been optimized, it's got an
    // instance-specific symbol table to check; but if it hasn't been
    // optimized, we check the symbol table int he master.
    for (int i = firstparam();  i < lastparam();  ++i) {
        const Symbol *sym = optimized ? symbol(i) : mastersymbol(i);
        if (! sym->everused())
            continue;
        if (sym->typespec().is_closure())
            continue;   // Closures can't have instance override values
        if ((sym->valuesource() == Symbol::InstanceVal || sym->valuesource() == Symbol::DefaultVal)
            && memcmp (param_storage(i), b.param_storage(i),
                       sym->typespec().simpletype().size())) {
            return false;
        }
    }

    if (m_run_lazily != b.m_run_lazily) {
        return false;
    }

    // The connection list need to be the same for the two shaders.
    if (m_connections.size() != b.m_connections.size()) {
        return false;
    }
    if (m_connections != b.m_connections) {
        return false;
    }

    // If there are no "local" ops or symbols, this instance hasn't been
    // optimized yet.  In that case, we've already done enough checking,
    // since the masters being the same and having the same instance
    // params and connections is all it takes.  The rest (below) only
    // comes into play after instances are more fully elaborated from
    // their masters in order to be optimized.
    if (!optimized) {
        return true;
    }

    // Same symbol table
    if (! equivalent (m_instsymbols, b.m_instsymbols)) {
        return false;
    }

    // Same opcodes to run
    if (! equivalent (m_instops, b.m_instops)) {
        return false;
    }
    // Same arguments to the ops
    if (m_instargs != b.m_instargs) {
        return false;
    }

    // Parameter and code ranges
    if (m_firstparam != b.m_firstparam ||
        m_lastparam != b.m_lastparam ||
        m_maincodebegin != b.m_maincodebegin ||
        m_maincodeend != b.m_maincodeend ||
        m_Psym != b.m_Psym || m_Nsym != b.m_Nsym) {
        return false;
    }

    // Nothing left to check, they must be identical!
    return true;
}
コード例 #8
0
llvm::Function*
BackendLLVM::build_llvm_instance (bool groupentry)
{
    // Make a layer function: void layer_func(ShaderGlobals*, GroupData*)
    // Note that the GroupData* is passed as a void*.
    std::string unique_layer_name = Strutil::format ("%s_%d", inst()->layername(), inst()->id());

    ll.current_function (
           ll.make_function (unique_layer_name,
                             !groupentry, // fastcall for non-entry layer functions
                             ll.type_void(), // return type
                             llvm_type_sg_ptr(), llvm_type_groupdata_ptr()));

    // Get shader globals and groupdata pointers
    m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
    m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;

    llvm::BasicBlock *entry_bb = ll.new_basic_block (unique_layer_name);
    m_exit_instance_block = NULL;

    // Set up a new IR builder
    ll.new_builder (entry_bb);
#if 0 /* helpful for debuggin */
    if (llvm_debug() && groupentry)
        llvm_gen_debug_printf (Strutil::format("\n\n\n\nGROUP! %s",group().name()));
    if (llvm_debug())
        llvm_gen_debug_printf (Strutil::format("enter layer %s %s",
                                  inst()->layername(), inst()->shadername()));
#endif
    if (shadingsys().countlayerexecs())
        ll.call_function ("osl_incr_layers_executed", sg_void_ptr());

    if (groupentry) {
        if (m_num_used_layers > 1) {
            // If this is the group entry point, clear all the "layer
            // executed" bits.  If it's not the group entry (but rather is
            // an upstream node), then set its bit!
            int sz = (m_num_used_layers + 3) & (~3);  // round up to 32 bits
            ll.op_memset (ll.void_ptr(layer_run_ptr(0)), 0, sz, 4 /*align*/);
        }
        // Group entries also need to allot space for ALL layers' params
        // that are closures (to avoid weird order of layer eval problems).
        for (int i = 0;  i < group().nlayers();  ++i) {
            ShaderInstance *gi = group()[i];
            if (gi->unused())
                continue;
            FOREACH_PARAM (Symbol &sym, gi) {
               if (sym.typespec().is_closure_based()) {
                    int arraylen = std::max (1, sym.typespec().arraylength());
                    llvm::Value *val = ll.constant_ptr(NULL, ll.type_void_ptr());
                    for (int a = 0; a < arraylen;  ++a) {
                        llvm::Value *arrind = sym.typespec().is_array() ? ll.constant(a) : NULL;
                        llvm_store_value (val, sym, 0, arrind, 0);
                    }
                }
            }
            // Unconditionally execute earlier layers that are not lazy
            if (! gi->run_lazily() && i < group().nlayers()-1)
                llvm_call_layer (i, true /* unconditionally run */);
        }
    }

    // Setup the symbols
    m_named_values.clear ();
    BOOST_FOREACH (Symbol &s, inst()->symbols()) {
        // Skip constants -- we always inline scalar constants, and for
        // array constants we will just use the pointers to the copy of
        // the constant that belongs to the instance.
        if (s.symtype() == SymTypeConst)
            continue;
        // Skip structure placeholders
        if (s.typespec().is_structure())
            continue;
        // Allocate space for locals, temps, aggregate constants
        if (s.symtype() == SymTypeLocal || s.symtype() == SymTypeTemp ||
                s.symtype() == SymTypeConst)
            getOrAllocateLLVMSymbol (s);
        // Set initial value for constants, closures, and strings that are
        // not parameters.
        if (s.symtype() != SymTypeParam && s.symtype() != SymTypeOutputParam &&
            s.symtype() != SymTypeGlobal &&
            (s.is_constant() || s.typespec().is_closure_based() ||
             s.typespec().is_string_based() || 
             ((s.symtype() == SymTypeLocal || s.symtype() == SymTypeTemp)
              && shadingsys().debug_uninit())))
            llvm_assign_initial_value (s);
        // If debugnan is turned on, globals check that their values are ok
        if (s.symtype() == SymTypeGlobal && shadingsys().debug_nan()) {
            TypeDesc t = s.typespec().simpletype();
            if (t.basetype == TypeDesc::FLOAT) { // just check float-based types
                int ncomps = t.numelements() * t.aggregate;
                llvm::Value *args[] = { ll.constant(ncomps), llvm_void_ptr(s),
                     ll.constant((int)s.has_derivs()), sg_void_ptr(), 
                     ll.constant(ustring(inst()->shadername())),
                     ll.constant(0), ll.constant(s.name()),
                     ll.constant(0), ll.constant(ncomps),
                     ll.constant("<none>")
                };
                ll.call_function ("osl_naninf_check", args, 10);
            }
        }
    }
    // make a second pass for the parameters (which may make use of
    // locals and constants from the first pass)
    FOREACH_PARAM (Symbol &s, inst()) {
        // Skip structure placeholders
        if (s.typespec().is_structure())
            continue;
        // Skip if it's never read and isn't connected
        if (! s.everread() && ! s.connected_down() && ! s.connected()
              && ! shadingsys().is_renderer_output(s.name()))
            continue;
        // Set initial value for params (may contain init ops)
        llvm_assign_initial_value (s);
    }

    // All the symbols are stack allocated now.

    // Mark all the basic blocks, including allocating llvm::BasicBlock
    // records for each.
    find_basic_blocks ();
    find_conditionals ();
    m_layers_already_run.clear ();

    build_llvm_code (inst()->maincodebegin(), inst()->maincodeend());

    if (llvm_has_exit_instance_block())
        ll.op_branch (m_exit_instance_block); // also sets insert point

    // Transfer all of this layer's outputs into the downstream shader's
    // inputs.
    for (int layer = this->layer()+1;  layer < group().nlayers();  ++layer) {
        ShaderInstance *child = group()[layer];
        for (int c = 0;  c < child->nconnections();  ++c) {
            const Connection &con (child->connection (c));
            if (con.srclayer == this->layer()) {
                ASSERT (con.src.arrayindex == -1 && con.src.channel == -1 &&
                        con.dst.arrayindex == -1 && con.dst.channel == -1 &&
                        "no support for individual element/channel connection");
                Symbol *srcsym (inst()->symbol (con.src.param));
                Symbol *dstsym (child->symbol (con.dst.param));
                llvm_run_connected_layers (*srcsym, con.src.param);
                // FIXME -- I'm not sure I understand this.  Isn't this
                // unnecessary if we wrote to the parameter ourself?
                llvm_assign_impl (*dstsym, *srcsym);
            }
        }
    }
    // llvm_gen_debug_printf ("done copying connections");

    // All done
#if 0 /* helpful for debugging */
    if (llvm_debug())
        llvm_gen_debug_printf (Strutil::format("exit layer %s %s",
                                   inst()->layername(), inst()->shadername()));
#endif
    ll.op_return();

    if (llvm_debug())
        std::cout << "layer_func (" << unique_layer_name << ") "<< this->layer() 
                  << "/" << group().nlayers() << " after llvm  = " 
                  << ll.bitcode_string(ll.current_function()) << "\n";

    ll.end_builder();  // clear the builder

    return ll.current_function();
}
コード例 #9
0
llvm::Type *
BackendLLVM::llvm_type_groupdata ()
{
    // If already computed, return it
    if (m_llvm_type_groupdata)
        return m_llvm_type_groupdata;

    std::vector<llvm::Type*> fields;
    int offset = 0;
    int order = 0;

    if (llvm_debug() >= 2)
        std::cout << "Group param struct:\n";

    // First, add the array that tells if each layer has run.  But only make
    // slots for the layers that may be called/used.
    if (llvm_debug() >= 2)
        std::cout << "  layers run flags: " << m_num_used_layers
                  << " at offset " << offset << "\n";
    int sz = (m_num_used_layers + 3) & (~3);  // Round up to 32 bit boundary
    fields.push_back (ll.type_array (ll.type_bool(), sz));
    offset += sz * sizeof(bool);
    ++order;

    // Now add the array that tells which userdata have been initialized,
    // and the space for the userdata values.
    int nuserdata = (int) group().m_userdata_names.size();
    if (nuserdata) {
        if (llvm_debug() >= 2)
            std::cout << "  userdata initialized flags: " << nuserdata
                      << " at offset " << offset << ", field " << order << "\n";
        ustring *names = & group().m_userdata_names[0];
        TypeDesc *types = & group().m_userdata_types[0];
        int *offsets = & group().m_userdata_offsets[0];
        int sz = (nuserdata + 3) & (~3);
        fields.push_back (ll.type_array (ll.type_bool(), sz));
        offset += nuserdata * sizeof(bool);
        ++order;
        for (int i = 0; i < nuserdata; ++i) {
            TypeDesc type = types[i];
            int n = type.numelements() * 3;   // always make deriv room
            type.arraylen = n;
            fields.push_back (llvm_type (type));
            // Alignment
            int align = type.basesize();
            offset = OIIO::round_to_multiple_of_pow2 (offset, align);
            if (llvm_debug() >= 2)
                std::cout << "  userdata " << names[i] << ' ' << type
                          << ", field " << order << ", offset " << offset << "\n";
            offsets[i] = offset;
            offset += int(type.size());
            ++order;
        }
    }

    // For each layer in the group, add entries for all params that are
    // connected or interpolated, and output params.  Also mark those
    // symbols with their offset within the group struct.
    m_param_order_map.clear ();
    for (int layer = 0;  layer < group().nlayers();  ++layer) {
        ShaderInstance *inst = group()[layer];
        if (inst->unused())
            continue;
        FOREACH_PARAM (Symbol &sym, inst) {
            TypeSpec ts = sym.typespec();
            if (ts.is_structure())  // skip the struct symbol itself
                continue;
            const int arraylen = std::max (1, sym.typespec().arraylength());
            const int derivSize = (sym.has_derivs() ? 3 : 1);
            ts.make_array (arraylen * derivSize);
            fields.push_back (llvm_type (ts));

            // Alignment
            size_t align = sym.typespec().is_closure_based() ? sizeof(void*) :
                    sym.typespec().simpletype().basesize();
            if (offset & (align-1))
                offset += align - (offset & (align-1));
            if (llvm_debug() >= 2)
                std::cout << "  " << inst->layername() 
                          << " (" << inst->id() << ") " << sym.mangled()
                          << " " << ts.c_str() << ", field " << order 
                          << ", size " << derivSize * int(sym.size())
                          << ", offset " << offset << std::endl;
            sym.dataoffset ((int)offset);
            offset += derivSize* int(sym.size());

            m_param_order_map[&sym] = order;
            ++order;
        }
    }
コード例 #10
0
llvm::Function*
RuntimeOptimizer::build_llvm_instance (bool groupentry)
{
    // Make a layer function: void layer_func(ShaderGlobals*, GroupData*)
    // Note that the GroupData* is passed as a void*.
    std::string unique_layer_name = Strutil::format ("%s_%d", inst()->layername().c_str(), inst()->id());

    m_layer_func = llvm::cast<llvm::Function>(m_llvm_module->getOrInsertFunction(unique_layer_name,
                    llvm_type_void(), llvm_type_sg_ptr(),
                    llvm_type_groupdata_ptr(), NULL));
    // Use fastcall for non-entry layer functions to encourage register calling
    if (!groupentry) m_layer_func->setCallingConv(llvm::CallingConv::Fast);
    llvm::Function::arg_iterator arg_it = m_layer_func->arg_begin();
    // Get shader globals pointer
    m_llvm_shaderglobals_ptr = arg_it++;
    m_llvm_groupdata_ptr = arg_it++;

    llvm::BasicBlock *entry_bb = llvm_new_basic_block (unique_layer_name);

    // Set up a new IR builder
    delete m_builder;
    m_builder = new llvm::IRBuilder<> (entry_bb);
    // llvm_gen_debug_printf (std::string("enter layer ")+inst()->shadername());

    if (groupentry) {
        if (m_num_used_layers > 1) {
            // If this is the group entry point, clear all the "layer
            // executed" bits.  If it's not the group entry (but rather is
            // an upstream node), then set its bit!
            int sz = (m_num_used_layers + 3) & (~3);  // round up to 32 bits
            llvm_memset (llvm_void_ptr(layer_run_ptr(0)), 0, sz, 4 /*align*/);
        }
        // Group entries also need to allot space for ALL layers' params
        // that are closures (to avoid weird order of layer eval problems).
        for (int i = 0;  i < group().nlayers();  ++i) {
            ShaderInstance *gi = group()[i];
            if (gi->unused())
                continue;
            FOREACH_PARAM (Symbol &sym, gi) {
               if (sym.typespec().is_closure_based()) {
                    int arraylen = std::max (1, sym.typespec().arraylength());
                    llvm::Value *val = llvm_constant_ptr(NULL, llvm_type_void_ptr());
                    for (int a = 0; a < arraylen;  ++a) {
                        llvm::Value *arrind = sym.typespec().is_array() ? llvm_constant(a) : NULL;
                        llvm_store_value (val, sym, 0, arrind, 0);
                    }
                }
            }
            // Unconditionally execute earlier layers that are not lazy
            if (! gi->run_lazily() && i < group().nlayers()-1)
                llvm_call_layer (i, true /* unconditionally run */);
        }
    }

    // Setup the symbols
    m_named_values.clear ();
    BOOST_FOREACH (Symbol &s, inst()->symbols()) {
        // Skip non-array constants -- we always inline them
        if (s.symtype() == SymTypeConst && !s.typespec().is_array())
            continue;
        // Skip structure placeholders
        if (s.typespec().is_structure())
            continue;
        // Allocate space for locals, temps, aggregate constants
        if (s.symtype() == SymTypeLocal || s.symtype() == SymTypeTemp ||
                s.symtype() == SymTypeConst)
            getOrAllocateLLVMSymbol (s);
        // Set initial value for constants, closures, and strings that are
        // not parameters.
        if (s.symtype() != SymTypeParam && s.symtype() != SymTypeOutputParam &&
            (s.is_constant() || s.typespec().is_closure_based() ||
             s.typespec().is_string_based()))
            llvm_assign_initial_value (s);
        // If debugnan is turned on, globals check that their values are ok
        if (s.symtype() == SymTypeGlobal && m_shadingsys.debug_nan()) {
            TypeDesc t = s.typespec().simpletype();
            if (t.basetype == TypeDesc::FLOAT) { // just check float-based types
                int ncomps = t.numelements() * t.aggregate;
                llvm::Value *args[] = { llvm_constant(ncomps), llvm_void_ptr(s),
                     llvm_constant((int)s.has_derivs()), sg_void_ptr(), 
                     llvm_constant(ustring(inst()->shadername())),
                     llvm_constant(0), llvm_constant(s.name()) };
                llvm_call_function ("osl_naninf_check", args, 7);
            }
        }
    }
    // make a second pass for the parameters (which may make use of
    // locals and constants from the first pass)
    FOREACH_PARAM (Symbol &s, inst()) {
        // Skip structure placeholders
        if (s.typespec().is_structure())
            continue;
        // Skip if it's never read and isn't connected
        if (! s.everread() && ! s.connected_down() && ! s.connected())
            continue;
        // Set initial value for params (may contain init ops)
        llvm_assign_initial_value (s);
    }

    // All the symbols are stack allocated now.

    // Mark all the basic blocks, including allocating llvm::BasicBlock
    // records for each.
    find_basic_blocks (true);
    find_conditionals ();
    m_layers_already_run.clear ();

    build_llvm_code (inst()->maincodebegin(), inst()->maincodeend());

    // Transfer all of this layer's outputs into the downstream shader's
    // inputs.
    for (int layer = m_layer+1;  layer < group().nlayers();  ++layer) {
        ShaderInstance *child = m_group[layer];
        for (int c = 0;  c < child->nconnections();  ++c) {
            const Connection &con (child->connection (c));
            if (con.srclayer == m_layer) {
                ASSERT (con.src.arrayindex == -1 && con.src.channel == -1 &&
                        con.dst.arrayindex == -1 && con.dst.channel == -1 &&
                        "no support for individual element/channel connection");
                Symbol *srcsym (inst()->symbol (con.src.param));
                Symbol *dstsym (child->symbol (con.dst.param));
                llvm_run_connected_layers (*srcsym, con.src.param);
                // FIXME -- I'm not sure I understand this.  Isn't this
                // unnecessary if we wrote to the parameter ourself?
                llvm_assign_impl (*dstsym, *srcsym);
            }
        }
    }
    // llvm_gen_debug_printf ("done copying connections");

    // All done
    // llvm_gen_debug_printf (std::string("exit layer ")+inst()->shadername());
    builder().CreateRetVoid();

    if (shadingsys().llvm_debug())
        llvm::outs() << "layer_func (" << unique_layer_name << ") after llvm  = " << *m_layer_func << "\n";

    delete m_builder;
    m_builder = NULL;

    return m_layer_func;
}
コード例 #11
0
ファイル: MaterialInstance.cpp プロジェクト: AMDmi3/shiny
	void MaterialInstance::createForConfiguration (const std::string& configuration)
	{
		bool res = mMaterial->createConfiguration(configuration);
		if (!res)
			return; // listener was false positive

		if (mListener)
			mListener->requestedConfiguration (this, configuration);

		mFactory->setActiveConfiguration (configuration);

		bool allowFixedFunction = true;
		if (!mShadersEnabled && hasProperty("allow_fixed_function"))
		{
			allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
		}

		// get passes of the top-most parent
		PassVector passes = getPasses();
		for (PassVector::iterator it = passes.begin(); it != passes.end(); ++it)
		{
			boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration);
			it->copyAll (pass.get(), this);

			// texture samplers used in the shaders
			std::vector<std::string> usedTextureSamplersVertex;
			std::vector<std::string> usedTextureSamplersFragment;

			PropertySetGet* context = this;

			// create or retrieve shaders
			if (mShadersEnabled || !allowFixedFunction)
			{
				it->setContext(context);
				it->mShaderProperties.setContext(context);
				if (it->hasProperty("vertex_program"))
				{
					ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
					ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
					if (v)
					{
						pass->assignProgram (GPT_Vertex, v->getName());
						v->setUniformParameters (pass, &it->mShaderProperties);

						std::vector<std::string> sharedParams = v->getSharedParameters ();
						for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
						{
							pass->addSharedParameter (GPT_Vertex, *it);
						}

						std::vector<std::string> vector = v->getUsedSamplers ();
						usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
					}
				}
				if (it->hasProperty("fragment_program"))
				{
					ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
					ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
					if (f)
					{
						pass->assignProgram (GPT_Fragment, f->getName());
						f->setUniformParameters (pass, &it->mShaderProperties);

						std::vector<std::string> sharedParams = f->getSharedParameters ();
						for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
						{
							pass->addSharedParameter (GPT_Fragment, *it);
						}

						std::vector<std::string> vector = f->getUsedSamplers ();
						usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
					}
				}
			}

			// create texture units
			std::vector<MaterialInstanceTextureUnit> texUnits = it->getTexUnits();
			int i=0;
			for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits.begin(); texIt  != texUnits.end(); ++texIt )
			{
				// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
				bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
				bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
				if (  (foundVertex || foundFragment)
						|| ((!mShadersEnabled && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
				{
					boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState ();
					texIt->copyAll (texUnit.get(), context);

					mTexUnits.push_back(texUnit);

					// set texture unit indices (required by GLSL)
					if (mShadersEnabled && mFactory->getCurrentLanguage () == Language_GLSL)
					{
						pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);

						++i;
					}
				}
			}
		}
	}
コード例 #12
0
ファイル: MaterialInstance.cpp プロジェクト: 0xmono/openmw
	bool MaterialInstance::createForConfiguration (const std::string& configuration, unsigned short lodIndex)
	{
		if (mFailedToCreate)
			return false;
		try{
			mMaterial->ensureLoaded();
			bool res = mMaterial->createConfiguration(configuration, lodIndex);
			if (!res)
				return false; // listener was false positive

			if (mListener)
				mListener->requestedConfiguration (this, configuration);

			mFactory->setActiveConfiguration (configuration);
			mFactory->setActiveLodLevel (lodIndex);

			bool allowFixedFunction = true;
			if (!mShadersEnabled && hasProperty("allow_fixed_function"))
			{
				allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
			}

			bool useShaders = mShadersEnabled || !allowFixedFunction;

			// get passes of the top-most parent
			PassVector* passes = getParentPasses();
			if (passes->empty())
				throw std::runtime_error ("material \"" + mName + "\" does not have any passes");

			for (PassVector::iterator it = passes->begin(); it != passes->end(); ++it)
			{
				boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration, lodIndex);
				it->copyAll (pass.get(), this);

				// texture samplers used in the shaders
				std::vector<std::string> usedTextureSamplersVertex;
				std::vector<std::string> usedTextureSamplersFragment;

				PropertySetGet* context = this;

				// create or retrieve shaders
				bool hasVertex = it->hasProperty("vertex_program")
						&& !retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get().empty();
				bool hasFragment = it->hasProperty("fragment_program")
						&& !retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get().empty();
				if (useShaders)
				{
					it->setContext(context);
					it->mShaderProperties.setContext(context);
					if (hasVertex)
					{
						ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
						ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
						if (v)
						{
							pass->assignProgram (GPT_Vertex, v->getName());
							v->setUniformParameters (pass, &it->mShaderProperties);

							std::vector<std::string> sharedParams = v->getSharedParameters ();
							for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
							{
								pass->addSharedParameter (GPT_Vertex, *it2);
							}

							std::vector<std::string> vector = v->getUsedSamplers ();
							usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
						}
					}
					if (hasFragment)
					{
						ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
						ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
						if (f)
						{
							pass->assignProgram (GPT_Fragment, f->getName());
							f->setUniformParameters (pass, &it->mShaderProperties);

							std::vector<std::string> sharedParams = f->getSharedParameters ();
							for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
							{
								pass->addSharedParameter (GPT_Fragment, *it2);
							}

							std::vector<std::string> vector = f->getUsedSamplers ();
							usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
						}
					}
				}

				// create texture units
				std::vector<MaterialInstanceTextureUnit>* texUnits = &it->mTexUnits;
				int i=0;
				for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits->begin(); texIt  != texUnits->end(); ++texIt )
				{
					// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
					bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
					bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
					if (  (foundVertex || foundFragment)
							|| (((!useShaders || (!hasVertex || !hasFragment)) && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
					{
						boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState (texIt->getName());
						texIt->copyAll (texUnit.get(), context);

						mTexUnits.push_back(texUnit);

						// set texture unit indices (required by GLSL)
						if (useShaders && ((hasVertex && foundVertex) || (hasFragment && foundFragment)) && mFactory->getCurrentLanguage () == Language_GLSL)
						{
							pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);

							++i;
						}
					}
				}
			}

			if (mListener)
				mListener->createdConfiguration (this, configuration);
			return true;

		} catch (std::runtime_error& e)
		{
			destroyAll();
			mFailedToCreate = true;
			std::stringstream msg;
			msg << "Error while creating material " << mName << ": " << e.what();
			std::cerr << msg.str() << std::endl;
			mFactory->logError(msg.str());
			return false;
		}
	}