static INLINE CGparameter d3d9_cg_find_param_from_semantic(
      CGparameter param, const char *sem)
{
   for (; param; param = cgGetNextParameter(param))
   {
      const char *semantic = NULL;
      if (cgGetParameterType(param) == CG_STRUCT)
      {
         CGparameter ret = d3d9_cg_find_param_from_semantic(
               cgGetFirstStructParameter(param), sem);

         if (ret)
            return ret;
      }

      if (     cgGetParameterDirection(param)   != CG_IN
            || cgGetParameterVariability(param) != CG_VARYING)
         continue;

      semantic = cgGetParameterSemantic(param);
      if (!semantic)
         continue;

      if (string_is_equal(sem, semantic) &&
            d3d9_cg_validate_param_name(cgGetParameterName(param)))
         return param;
   }

   return NULL;
}
Exemple #2
0
cgfxRCPtr<cgfxVertexAttribute> cgfxVaryingParameter::setupAttribute(
    MString name, 
    const MString& semantic, 
    CGparameter parameter, 
    cgfxRCPtr<cgfxVertexAttribute>& vertexAttributes
)
{
	// Does a varying parameter of this name already exist?
	cgfxRCPtr<cgfxVertexAttribute>* attribute = &vertexAttributes;
	while( attribute->isNull() == false )
	{
		if( (*attribute)->fName == name)
		{
			return *attribute;
		}
		attribute = &(*attribute)->fNext;
	}

	// Add a new input for this parameter
	cgfxRCPtr<cgfxVertexAttribute> attr = cgfxRCPtr<cgfxVertexAttribute>(new cgfxVertexAttribute());
	*attribute = attr;

	// Setup the varying parameter description
	attr->fName = name;
	attr->fType = cgGetTypeString( cgGetParameterType( parameter));
	attr->fSemantic = semantic;
	return attr;
}
static INLINE CGparameter find_param_from_semantic(
      CGparameter param, const char *sem)
{
   while (param)
   {
      if (cgGetParameterType(param) == CG_STRUCT)
      {
         CGparameter ret = find_param_from_semantic(
               cgGetFirstStructParameter(param), sem);

         if (ret)
            return ret;
      }
      else
      {
         if (cgGetParameterSemantic(param) &&
               !strcmp(sem, cgGetParameterSemantic(param)) &&
               cgGetParameterDirection(param) == CG_IN &&
               cgGetParameterVariability(param) == CG_VARYING &&
               validate_param_name(cgGetParameterName(param)))
            return param;
      }
      param = cgGetNextParameter(param);
   }

   return NULL;
}
Exemple #4
0
/* iterate all parameters and record input variyings
   with their semantic and resource index
*/
void CD3DCG::fillParameterMap(std::vector<parameterEntry> &map, CGparameter param)
{
	parameterEntry mapEntry;
	while (param) {
		if(cgGetParameterType(param)==CG_STRUCT)
			fillParameterMap(map,cgGetFirstStructParameter(param));
		else
			if (cgGetParameterDirection(param) == CG_IN && cgGetParameterVariability(param) == CG_VARYING) {
				mapEntry.rIndex = cgGetParameterResourceIndex(param);
				mapEntry.semantic = cgGetParameterSemantic(param);
				mapEntry.isKnownParam = isKnownParameter(cgGetParameterName(param));
				if(map.size()<mapEntry.rIndex+1)
					map.resize(mapEntry.rIndex+1);
				map[mapEntry.rIndex] = mapEntry;
			}
		param = cgGetNextParameter(param);
	}
}
Exemple #5
0
inline void cgfxVaryingParameter::addRecursive(
    CGparameter parameter,
    cgfxVaryingParameter**& nextParameter
)
{
	if( cgGetParameterVariability( parameter) == CG_VARYING)
	{
		if( cgGetParameterType( parameter) == CG_STRUCT)
		{
			CGparameter input = cgGetFirstStructParameter( parameter);
			while( input)
			{
				addRecursive( input, nextParameter);
				input = cgGetNextParameter( input);
			}
		}
		else if( cgIsParameterReferenced( parameter))
		{
			*nextParameter = new cgfxVaryingParameter( parameter);
			nextParameter = &(*nextParameter)->fNext;
		}
	}
}
Exemple #6
0
	//---------------------------------------------------------------------
	void CgProgram::recurseParams(CGparameter parameter, size_t contextArraySize)
	{
		while (parameter != 0)
		{
			// Look for uniform parameters only
			// Don't bother enumerating unused parameters, especially since they will
			// be optimised out and therefore not in the indexed versions
			CGtype paramType = cgGetParameterType(parameter);

			if (cgGetParameterVariability(parameter) == CG_UNIFORM &&
				paramType != CG_SAMPLER1D &&
				paramType != CG_SAMPLER2D &&
				paramType != CG_SAMPLER3D &&
				paramType != CG_SAMPLERCUBE &&
				paramType != CG_SAMPLERRECT &&
				cgGetParameterDirection(parameter) != CG_OUT && 
				cgIsParameterReferenced(parameter))
			{
				int arraySize;

				switch(paramType)
				{
				case CG_STRUCT:
					recurseParams(cgGetFirstStructParameter(parameter));
					break;
				case CG_ARRAY:
					// Support only 1-dimensional arrays
					arraySize = cgGetArraySize(parameter, 0);
					recurseParams(cgGetArrayParameter(parameter, 0), (size_t)arraySize);
					break;
				default:
					// Normal path (leaf)
					String paramName = cgGetParameterName(parameter);
					size_t logicalIndex = cgGetParameterResourceIndex(parameter);

					// Get the parameter resource, to calculate the physical index
					CGresource res = cgGetParameterResource(parameter);
					bool isRegisterCombiner = false;
					size_t regCombinerPhysicalIndex = 0;
					switch (res)
					{
					case CG_COMBINER_STAGE_CONST0:
						// register combiner, const 0
						// the index relates to the texture stage; store this as (stage * 2) + 0
						regCombinerPhysicalIndex = logicalIndex * 2;
						isRegisterCombiner = true;
						break;
					case CG_COMBINER_STAGE_CONST1:
						// register combiner, const 1
						// the index relates to the texture stage; store this as (stage * 2) + 1
						regCombinerPhysicalIndex = (logicalIndex * 2) + 1;
						isRegisterCombiner = true;
						break;
					default:
						// normal constant
						break;
					}

					// Trim the '[0]' suffix if it exists, we will add our own indexing later
					if (StringUtil::endsWith(paramName, "[0]", false))
					{
						paramName.erase(paramName.size() - 3);
					}


					GpuConstantDefinition def;
					def.arraySize = contextArraySize;
					mapTypeAndElementSize(paramType, isRegisterCombiner, def);

					if (def.constType == GCT_UNKNOWN)
					{
						LogManager::getSingleton().logMessage(
							"Problem parsing the following Cg Uniform: '"
							+ paramName + "' in file " + mName);
						// next uniform
						parameter = cgGetNextParameter(parameter);
						continue;
					}
					if (isRegisterCombiner)
					{
						def.physicalIndex = regCombinerPhysicalIndex;
					}
					else
					{
						// base position on existing buffer contents
						if (def.isFloat())
						{
							def.physicalIndex = mFloatLogicalToPhysical->bufferSize;
						}
						else
						{
							def.physicalIndex = mIntLogicalToPhysical->bufferSize;
						}
					}

					def.logicalIndex = logicalIndex;
					if( mParametersMap.find(paramName) == mParametersMap.end())
					{
						mParametersMap.insert(GpuConstantDefinitionMap::value_type(paramName, def));
						mParametersMapSizeAsBuffer += sizeof(size_t);
						mParametersMapSizeAsBuffer += paramName.size();
						mParametersMapSizeAsBuffer += sizeof(GpuConstantDefinition);
					}

					// Record logical / physical mapping
					if (def.isFloat())
					{
											OGRE_LOCK_MUTEX(mFloatLogicalToPhysical->mutex);
						mFloatLogicalToPhysical->map.insert(
							GpuLogicalIndexUseMap::value_type(def.logicalIndex, 
								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
						mFloatLogicalToPhysical->bufferSize += def.arraySize * def.elementSize;
					}
					else
					{
											OGRE_LOCK_MUTEX(mIntLogicalToPhysical->mutex);
						mIntLogicalToPhysical->map.insert(
							GpuLogicalIndexUseMap::value_type(def.logicalIndex, 
								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL)));
						mIntLogicalToPhysical->bufferSize += def.arraySize * def.elementSize;
					}

					break;
				}                   
			}

			// now handle uniform samplers. This is needed to fix their register positions
			// if delegating to a GLSL shader.
			if (mDelegate && cgGetParameterVariability(parameter) == CG_UNIFORM && (
				paramType == CG_SAMPLER1D ||
				paramType == CG_SAMPLER2D ||
				paramType == CG_SAMPLER3D ||
				paramType == CG_SAMPLERCUBE ||
				paramType == CG_SAMPLERRECT) &&
				cgGetParameterDirection(parameter) != CG_OUT && 
				cgIsParameterReferenced(parameter))
			{
				String paramName = cgGetParameterName(parameter);
				CGresource res = cgGetParameterResource(parameter);
				int pos = -1;
				switch (res)
				{
				case CG_TEXUNIT0: pos = 0; break;
				case CG_TEXUNIT1: pos = 1; break;
				case CG_TEXUNIT2: pos = 2; break;
				case CG_TEXUNIT3: pos = 3; break;
				case CG_TEXUNIT4: pos = 4; break;
				case CG_TEXUNIT5: pos = 5; break;
				case CG_TEXUNIT6: pos = 6; break;
				case CG_TEXUNIT7: pos = 7; break;
				case CG_TEXUNIT8: pos = 8; break;
				case CG_TEXUNIT9: pos = 9; break;
				case CG_TEXUNIT10: pos = 10; break;
				case CG_TEXUNIT11: pos = 11; break;
				case CG_TEXUNIT12: pos = 12; break;
				case CG_TEXUNIT13: pos = 13; break;
				case CG_TEXUNIT14: pos = 14; break;
				case CG_TEXUNIT15: pos = 15; break;
#if(CG_VERSION_NUM >= 3000)
				case CG_TEXUNIT16: pos = 16; break;
				case CG_TEXUNIT17: pos = 17; break;
				case CG_TEXUNIT18: pos = 18; break;
				case CG_TEXUNIT19: pos = 19; break;
				case CG_TEXUNIT20: pos = 20; break;
				case CG_TEXUNIT21: pos = 21; break;
				case CG_TEXUNIT22: pos = 22; break;
				case CG_TEXUNIT23: pos = 23; break;
				case CG_TEXUNIT24: pos = 24; break;
				case CG_TEXUNIT25: pos = 25; break;
				case CG_TEXUNIT26: pos = 26; break;
				case CG_TEXUNIT27: pos = 27; break;
				case CG_TEXUNIT28: pos = 28; break;
				case CG_TEXUNIT29: pos = 29; break;
				case CG_TEXUNIT30: pos = 30; break;
				case CG_TEXUNIT31: pos = 31; break;
#endif
				default:
					break;
				}
				if (pos != -1)
				{
					mSamplerRegisterMap.insert(std::make_pair(paramName, pos));
				}
			}

			// Get next
			parameter = cgGetNextParameter(parameter);
		}

		
	}
bool CgShaderProgramGL::setConstant(const io::stringc &Name, const f32* Buffer, s32 Count)
{
    if (!Buffer)
        return false;

    /* Get top-level parameter */
    CGparameter Param = cgGetNamedParameter(cgProgram_, Name.c_str());

    if (!Param)
        return false;

    /* Get array parameter */
    if (cgGetParameterType(Param) != CG_ARRAY)
        return false;

    s32 ArraySize = cgGetArraySize(Param, 0);

    for (s32 i = 0; i < ArraySize; ++i)
    {
        /* Get array element parameter */
        CGparameter ElementParam = cgGetArrayParameter(Param, i);

        switch (cgGetParameterType(ElementParam))
        {
        case CG_FLOAT:
            cgGLSetParameterArray1f(Param, 0, Count, Buffer);
            return true;
        case CG_FLOAT2:
            cgGLSetParameterArray2f(Param, 0, Count/2, Buffer);
            return true;
        case CG_FLOAT3:
            cgGLSetParameterArray3f(Param, 0, Count/3, Buffer);
            return true;
        case CG_FLOAT4:
            cgGLSetParameterArray4f(Param, 0, Count/4, Buffer);
            return true;
        case CG_FLOAT4x4:
            cgGLSetMatrixParameterArrayfc(Param, 0, Count/16, Buffer);
            return true;

        case CG_STRUCT:
        {
            /* Get structure field parameter */
            CGparameter FieldParam = cgGetFirstStructParameter(ElementParam);

            while (FieldParam)
            {
                switch (cgGetParameterType(FieldParam))
                {
                case CG_FLOAT:
                    cgGLSetParameter1f(FieldParam, *Buffer);
                    Buffer += 1;
                    break;
                case CG_FLOAT2:
                    cgGLSetParameter2fv(FieldParam, Buffer);
                    Buffer += 2;
                    break;
                case CG_FLOAT3:
                    cgGLSetParameter3fv(FieldParam, Buffer);
                    Buffer += 3;
                    break;
                case CG_FLOAT4:
                    cgGLSetParameter4fv(FieldParam, Buffer);
                    Buffer += 4;
                    break;
                case CG_FLOAT4x4:
                    cgGLSetMatrixParameterfc(FieldParam, Buffer);
                    Buffer += 16;
                    break;
                case CG_INT:
                    cgSetParameter1i(FieldParam, *((s32*)Buffer));
                    Buffer += 1;
                    break;
                default:
                    break;
                }

                FieldParam = cgGetNextParameter(FieldParam);
            }
        }
        break;

        default:
            break;
        }
    }

    return true;
}
static void AddParameter(JSON &json, CGparameter param)
{
    const char * const parameterName = cgGetParameterName(param);

    if (sVerbose)
    {
        puts(parameterName);
    }

    json.AddObject(parameterName);

    const CGtype type = cgGetParameterType(param);
    const CGtype baseType = cgGetParameterBaseType(param);
    int numRows = cgGetParameterRows(param);
    const int numColumns = cgGetParameterColumns(param);
    if (CG_ARRAY == type)
    {
        const int totalArraySize = cgGetArrayTotalSize(param);
        numRows *= totalArraySize;
    }
    json.AddString("type", cgGetTypeString(baseType));
    if (1 < numRows)
    {
        json.AddValue("rows", numRows);
    }
    if (1 < numColumns)
    {
        json.AddValue("columns", numColumns);
    }

    const int maxNumElements = (numColumns * numRows);
    int n;
    if (CG_FLOAT == baseType)
    {
        float * const values = (float *)malloc(maxNumElements * sizeof(float));
        const int numValues = cgGetParameterValuefr(param, maxNumElements, values);
        if (numValues)
        {
            for (n = 0; n < numValues; n++)
            {
                if (values[n] != 0.0f)
                {
                    break;
                }
            }
            if (n < numValues)
            {
                json.AddArray("values", true);
                json.BeginData(true);
                for (n = 0; n < numValues; n++)
                {
                    json.AddData(values[n]);
                }
                json.EndData();
                json.CloseArray(true);
            }
        }
        free(values);
    }
    else if (CG_INT == baseType)
    {
        int * const values = (int *)malloc(maxNumElements * sizeof(int));
        const int numValues = cgGetParameterValueir(param, maxNumElements, values);
        if (numValues)
        {
            for (n = 0; n < numValues; n++)
            {
                if (values[n])
                {
                    break;
                }
            }
            if (n < numValues)
            {
                json.AddArray("values", true);
                json.BeginData(true);
                for (n = 0; n < numValues; n++)
                {
                    json.AddData(values[n]);
                }
                json.EndData();
                json.CloseArray(true);
            }
        }
        free(values);
    }
    else if (CG_BOOL == baseType)
    {
        int * const values = (int *)malloc(maxNumElements * sizeof(int));
        const int numValues = cgGetParameterValueir(param, maxNumElements, values);
        if (numValues)
        {
            for (n = 0; n < numValues; n++)
            {
                if (values[n])
                {
                    break;
                }
            }
            if (n < numValues)
            {
                json.AddArray("values", true);
                json.BeginData(true);
                for (n = 0; n < numValues; n++)
                {
                    json.AddData(values[n]);
                }
                json.EndData();
                json.CloseArray(true);
            }
        }
        free(values);
    }

    json.CloseObject(); // parameter
}
	//---------------------------------------------------------------------
	void CgProgram::recurseParams(CGparameter parameter, size_t contextArraySize) const
	{
		while (parameter != 0)
        {
            // Look for uniform (non-sampler) parameters only
            // Don't bother enumerating unused parameters, especially since they will
            // be optimised out and therefore not in the indexed versions
            CGtype paramType = cgGetParameterType(parameter);

            if (cgGetParameterVariability(parameter) == CG_UNIFORM &&
                paramType != CG_SAMPLER1D &&
                paramType != CG_SAMPLER2D &&
                paramType != CG_SAMPLER3D &&
                paramType != CG_SAMPLERCUBE &&
                paramType != CG_SAMPLERRECT &&
                cgGetParameterDirection(parameter) != CG_OUT && 
                cgIsParameterReferenced(parameter))
            {
				int arraySize;

				switch(paramType)
				{
				case CG_STRUCT:
					recurseParams(cgGetFirstStructParameter(parameter));
					break;
				case CG_ARRAY:
					// Support only 1-dimensional arrays
					arraySize = cgGetArraySize(parameter, 0);
					recurseParams(cgGetArrayParameter(parameter, 0), (size_t)arraySize);
					break;
				default:
					// Normal path (leaf)
					String paramName = cgGetParameterName(parameter);
					size_t logicalIndex = cgGetParameterResourceIndex(parameter);

					// Get the parameter resource, to calculate the physical index
					CGresource res = cgGetParameterResource(parameter);
					bool isRegisterCombiner = false;
					size_t regCombinerPhysicalIndex = 0;
					switch (res)
					{
					case CG_COMBINER_STAGE_CONST0:
						// register combiner, const 0
						// the index relates to the texture stage; store this as (stage * 2) + 0
						regCombinerPhysicalIndex = logicalIndex * 2;
						isRegisterCombiner = true;
						break;
					case CG_COMBINER_STAGE_CONST1:
						// register combiner, const 1
						// the index relates to the texture stage; store this as (stage * 2) + 1
						regCombinerPhysicalIndex = (logicalIndex * 2) + 1;
						isRegisterCombiner = true;
						break;
					default:
						// normal constant
						break;
					}

					// Trim the '[0]' suffix if it exists, we will add our own indexing later
					if (StringUtil::endsWith(paramName, "[0]", false))
					{
						paramName.erase(paramName.size() - 3);
					}


					GpuConstantDefinition def;
					def.arraySize = contextArraySize;
					mapTypeAndElementSize(paramType, isRegisterCombiner, def);

					if (def.constType == GCT_UNKNOWN)
					{
						LogManager::getSingleton().logMessage(
							"Problem parsing the following Cg Uniform: '"
							+ paramName + "' in file " + mName);
						// next uniform
						continue;
					}
					if (isRegisterCombiner)
					{
						def.physicalIndex = regCombinerPhysicalIndex;
					}
					else
					{
						// base position on existing buffer contents
						if (def.isFloat())
						{
							def.physicalIndex = mFloatLogicalToPhysical.bufferSize;
						}
						else
						{
							def.physicalIndex = mIntLogicalToPhysical.bufferSize;
						}
					}


					mConstantDefs.map.insert(GpuConstantDefinitionMap::value_type(paramName, def));

					// Record logical / physical mapping
					if (def.isFloat())
					{
						OGRE_LOCK_MUTEX(mFloatLogicalToPhysical.mutex)
						mFloatLogicalToPhysical.map.insert(
							GpuLogicalIndexUseMap::value_type(logicalIndex, 
								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize)));
						mFloatLogicalToPhysical.bufferSize += def.arraySize * def.elementSize;
						mConstantDefs.floatBufferSize = mFloatLogicalToPhysical.bufferSize;
					}
					else
					{
						OGRE_LOCK_MUTEX(mIntLogicalToPhysical.mutex)
						mIntLogicalToPhysical.map.insert(
							GpuLogicalIndexUseMap::value_type(logicalIndex, 
								GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize)));
						mIntLogicalToPhysical.bufferSize += def.arraySize * def.elementSize;
						mConstantDefs.intBufferSize = mIntLogicalToPhysical.bufferSize;
					}

					// Deal with array indexing
					mConstantDefs.generateConstantDefinitionArrayEntries(paramName, def);

					break;
		
				}
					
            }
            // Get next
            parameter = cgGetNextParameter(parameter);
        }

        
    }
Exemple #10
0
void CCgMaterialRenderer::getUniformList()
{
	for(unsigned int i = 0; i < UniformInfo.size(); ++i)
		delete UniformInfo[i];

	UniformInfo.clear();

	for(unsigned int i = 0; i < 2; ++i)
	{
		CGenum Space = CG_GLOBAL;
		bool IsGlobal = 1;

		if(i == 1)
		{
			Space = CG_PROGRAM;
			IsGlobal = 0;
		}

		for(unsigned int j = 0; j < 3; ++j)
		{
			CGprogram* Program = 0;

			switch(j)
			{
			case 0:
				Program = &VertexProgram;
				break;
			case 1:
				Program = &FragmentProgram;
				break;
			case 2:
				Program = &GeometryProgram;
				break;
			}

			if(*Program)
			{
				CGparameter Parameter = cgGetFirstParameter(*Program, Space);

				while(Parameter)
				{
					if(cgGetParameterVariability(Parameter) == CG_UNIFORM && cgGetParameterDirection(Parameter) == CG_IN)
					{
						CCgUniform* Uniform = 0;

						CGtype Type = cgGetParameterType(Parameter);

						switch(Type)
						{
						case CG_FLOAT:
						case CG_FLOAT1:
							Uniform = new CCgUniform1f(Parameter, IsGlobal);
							break;
						case CG_FLOAT2:
							Uniform = new CCgUniform2f(Parameter, IsGlobal);
							break;
						case CG_FLOAT3:
							Uniform = new CCgUniform3f(Parameter, IsGlobal);
							break;
						case CG_FLOAT4:
							Uniform = new CCgUniform4f(Parameter, IsGlobal);
							break;
						case CG_INT:
						case CG_INT1:
							Uniform = new CCgUniform1i(Parameter, IsGlobal);
							break;
						case CG_INT2:
							Uniform = new CCgUniform2i(Parameter, IsGlobal);
							break;
						case CG_INT3:
							Uniform = new CCgUniform3i(Parameter, IsGlobal);
							break;
						case CG_INT4:
							Uniform = new CCgUniform4i(Parameter, IsGlobal);
							break;
						case CG_FLOAT4x4:
							Uniform = new CCgUniform4x4f(Parameter, IsGlobal);
							break;
						case CG_SAMPLER2D:
							Uniform = new CCgUniformSampler2D(Parameter, IsGlobal);
							break;
						}

						if(Uniform)
							UniformInfo.push_back(Uniform);
					}

					Parameter = cgGetNextParameter(Parameter);
				}
			}
		}
	}
}
Exemple #11
0
static int PubCGparam_func (PState pstate,PubFunction_t *fn, int n)
{
  CGparameter cgparam = NULL;

  if ((int)fn->upvalue > PCG_GET && (n<1 || FunctionPublish_getArg(pstate,1,LUXI_CLASS_CGPARAM,(void*)&cgparam)<1))
    return FunctionPublish_returnError(pstate,"1 cgparam required");

  switch((int)fn->upvalue){
    case PCG_NEW:
      {
        char *name;
        char *nametype;
        CGtype cgtype;
        CGtype basetype;
        int cnt = 1;

        if (n < 2 || FunctionPublish_getArg(pstate,3,LUXI_CLASS_STRING,(void*)&name,LUXI_CLASS_STRING,(void*)&nametype,LUXI_CLASS_INT,(void*)&cnt)<2)
          return FunctionPublish_returnError(pstate,"2 strings required");

        cgtype = cgGetType(nametype);
        basetype = cgGetTypeBase(cgtype);

        if (VIDCg_getConnector(name) || cgtype==CG_UNKNOWN_TYPE ||
          (basetype != CG_FLOAT && basetype != CG_INT && basetype != CG_BOOL))
          return FunctionPublish_returnError(pstate,"name already in use, or illegal cg base type (float, bool, int)");

        if (cgGetTypeClass(cgtype) == CG_PARAMETERCLASS_MATRIX && basetype != CG_FLOAT)
          return FunctionPublish_returnError(pstate,"only float matrix parameters allowed");

        cgparam = cnt > 1 ? cgCreateParameterArray(g_VID.cg.context,cgtype,cnt) : cgCreateParameter(g_VID.cg.context,cgtype);
        VIDCg_setConnector(name,cgparam);

        return FunctionPublish_returnType(pstate,LUXI_CLASS_CGPARAM,(void*)cgparam);
      }

      break;
    case PCG_DELETE:
      {
        int linked = cgGetNumConnectedToParameters(cgparam);
        if (linked == 0){
          VIDCg_setConnector(cgGetParameterName(cgparam),NULL);
          cgDestroyParameter(cgparam);
        }
        return FunctionPublish_returnInt(pstate,linked);
      }
      break;
    case PCG_GET:
      {
        char *name;
        if (n < 1 || !FunctionPublish_getArg(pstate,1,LUXI_CLASS_STRING,(void*)&name))
          return FunctionPublish_returnError(pstate,"1 string required");
        cgparam = VIDCg_getConnector(name);

        if (cgparam)
          return FunctionPublish_returnType(pstate,LUXI_CLASS_CGPARAM,(void*)cgparam);
        else
          return 0;
      }
      break;
    case PCG_VALUE:
      {
      CGtype cgtype = cgGetParameterType(cgparam);
      CGtype basetype = cgGetTypeBase(cgtype);
      CGtype classtype = cgGetTypeClass(cgtype);
      lxClassType ctype;

      Reference ref;
      float *matrix;
      StaticArray_t *starray;
      int read = 0;
      int offset = 0;
      int size;

      int into = (int)fn->upvalue == PCG_VALUEINTO;

      if (n==1 || into){
        int vector[4];


        switch(classtype){
        case CG_PARAMETERCLASS_SCALAR:
        case CG_PARAMETERCLASS_VECTOR:

          switch(basetype){
          case CG_FLOAT:
            ctype = LUXI_CLASS_FLOAT;
            read = cgGetParameterValuefc(cgparam,4,(float*)vector);
            break;
          case CG_BOOL:
            ctype = LUXI_CLASS_BOOLEAN;
            read = cgGetParameterValueic(cgparam,4,vector);
            break;
          case CG_INT:
            ctype = LUXI_CLASS_INT;
            read = cgGetParameterValueic(cgparam,4,vector);
            break;
          default:
            return 0;
          }
          return FunctionPublish_setRet(pstate,read,ctype,(void*)vector[0],ctype,(void*)vector[1],ctype,(void*)vector[2],ctype,(void*)vector[3]);
          break;
        case CG_PARAMETERCLASS_MATRIX:
          if (into){
            // get matrix first
            if (!FunctionPublish_getNArg(pstate,1,LUXI_CLASS_MATRIX44,(void*)&ref) || !Reference_get(ref,matrix))
              return FunctionPublish_returnError(pstate,"1 matrix4x4 required");
          }
          else{
            // create matrix
            matrix = PubMatrix4x4_alloc();
            ref = Reference_new(LUXI_CLASS_MATRIX44,matrix);
            Reference_makeVolatile(ref);
          }

          cgGetMatrixParameterfc(cgparam,matrix);
          return FunctionPublish_returnType(pstate,LUXI_CLASS_MATRIX44,REF2VOID(ref));
          break;
        case CG_PARAMETERCLASS_ARRAY:
          ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOATARRAY : LUXI_CLASS_INTARRAY;

          size = cgGetParameterColumns(cgparam)*cgGetParameterRows(cgparam)*cgGetArrayTotalSize(cgparam);
          if (into){
            // get array first
            if (FunctionPublish_getArgOffset(pstate,1,3,ctype,(void*)&ref,LUXI_CLASS_INT,(void*)&offset)<1 || !Reference_get(ref,starray) ||
              offset+size > starray->count)
              return FunctionPublish_returnError(pstate,"1 staticarray [1 int] required (with enough space)");
          }
          else{
            // create array
            starray = StaticArray_new(size,ctype,NULL,NULL);
          }

          offset = LUX_MIN(offset,(starray->count-1));
          read = LUX_MIN(read,(starray->count-offset));

          if (ctype == LUXI_CLASS_FLOATARRAY)
            cgGetParameterValuefc(cgparam,read,starray->floats);
          else
            cgGetParameterValueic(cgparam,read,starray->ints);

          return FunctionPublish_returnType(pstate,ctype,REF2VOID(starray->ref));
        }
      }
      else {
        // set
        lxVector4 vector;

        switch(classtype){
        case CG_PARAMETERCLASS_SCALAR:
        case CG_PARAMETERCLASS_VECTOR:
          ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOAT : LUXI_CLASS_INT;
          read = FunctionPublish_getArgOffset(pstate,1,n-1,ctype,(void*)&vector[0],ctype,(void*)&vector[1],ctype,(void*)&vector[2],ctype,(void*)&vector[3]);
          if (read > 0){
            switch(basetype){
            case CG_FLOAT:
              cgSetParameterValuefc(cgparam,n-1,vector);
              return 0;
            case CG_BOOL:
            case CG_INT:
              cgSetParameterValueic(cgparam,n-1,(int*)vector);
              return 0;
            default:
              return 0;
            }
          }
          break;
        case CG_PARAMETERCLASS_MATRIX:
          if (!FunctionPublish_getNArg(pstate,1,LUXI_CLASS_MATRIX44,(void*)&ref) || !Reference_get(ref,matrix))
            return FunctionPublish_returnError(pstate,"1 matrix4x4 required");
          cgSetMatrixParameterfc(cgparam,matrix);
          return 0;
        case CG_PARAMETERCLASS_ARRAY:
          ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOATARRAY : LUXI_CLASS_INTARRAY;
          size = cgGetParameterColumns(cgparam)*cgGetParameterRows(cgparam)*cgGetArrayTotalSize(cgparam);

          if (FunctionPublish_getArgOffset(pstate,1,3,ctype,(void*)&ref,LUXI_CLASS_INT,(void*)&offset) || !Reference_get(ref,starray)
            || offset+size > starray->count)
            return FunctionPublish_returnError(pstate,"1 staticarray [2 ints] required, with enough space");

          offset = LUX_MIN(offset,(starray->count-1));

          if (ctype == LUXI_CLASS_FLOATARRAY)
            cgSetParameterValuefc(cgparam,size,&starray->floats[offset]);
          else
            cgSetParameterValueic(cgparam,size,&starray->ints[offset]);
          return 0;
        default:
          return 0;
        }
      }
      }
    case PCG_SIZES:
      return FunctionPublish_setRet(pstate,3,LUXI_CLASS_INT,(void*)cgGetParameterColumns(cgparam),LUXI_CLASS_INT,(void*)cgGetParameterRows(cgparam),LUXI_CLASS_INT,(void*)cgGetArrayTotalSize(cgparam));
    default:
      break;
  }

  return 0;
}