/// <summary> /// Computes dot product of two operands. /// </summary> public Operand Dot(Operand in1, Operand in2) { if (in1.IsArray || !in1.Equals(in2)) { throw new IncompatibleOperandsException("Dot operation requires both formats to be the same."); } PinFormat fmt; if (!PinFormatHelper.IsVector(in1.Format, out fmt)) { throw new IncompatibleOperandsException("Dot operation requires both formats to be vectors."); } // We check if we can precache it, this is copy only op. if (in1.IsFixed && in2.IsFixed) { return(CreateFixed(fmt, in1.ArraySize, Math.MathHelper.Dot(in1.Value, in2.Value))); } // Else create temp and return. Operand tmp = CreateTemporary(fmt, in1.ArraySize); compiler.Mul(in1.Name, in2.Name, tmp.Name); return(tmp); }
protected override Pin[] CreateOutputs() { // We search for vector-* and *-vector operations. PinFormat scalar; if (PinFormatHelper.IsVector(inputs[0].Format, out scalar)) { // The result must be matrix. return(new Pin[] { inputs[0].Clone(this) }); } if (PinFormatHelper.IsVector(inputs[1].Format, out scalar)) { return(new Pin[] { inputs[1].Clone(this) }); } // We search for matrix-* and *-matrix operations. if (PinFormatHelper.IsMatrix(inputs[0].Format, out scalar)) { // The result must be matrix. return(new Pin[] { inputs[0].Clone(this) }); } if (PinFormatHelper.IsMatrix(inputs[1].Format, out scalar)) { // The result must be matrix. return(new Pin[] { inputs[1].Clone(this) }); } // Must be equal, we simply output. return(new Pin[] { inputs[0].Clone(this) }); }
/// <summary> /// Computes dot product of two operands. /// </summary> /// <returns>Result of operation.</returns> public void Dot(Operand in1, Operand in2, Operand outOp) { if (in1.IsArray || !in1.Equals(in2) || !outOp.IsWritable) { throw new IncompatibleOperandsException("Addition operation requires both formats to be the same."); } PinFormat fmt; if (!PinFormatHelper.IsVector(in1.Format, out fmt) || outOp.Format != fmt) { throw new IncompatibleOperandsException("Only vector types can be used in dot product, scalars must match vector types."); } // We check if we can precache it, this is copy only op. if (in1.IsFixed && in2.IsFixed) { Operand tmp = CreateFixed(in1.Format, in1.ArraySize, Math.MathHelper.Dot(in1.Value, in2.Value)); // We must create a mem copy. compiler.Mov(tmp.Name, outOp.Name); return; } compiler.Dot(in1.Name, in2.Name, outOp.Name); }
/// <summary> /// Multiplies two operands. /// </summary> /// <returns>Result of operation.</returns> public void Mul(Operand in1, Operand in2, Operand outOp) { if (in1.IsArray || !in1.Equals(in2) || !in1.Equals(outOp) || !outOp.IsWritable) { throw new IncompatibleOperandsException("Addition operation requires both formats to be the same."); } // We check if we can precache it, this is copy only op. if (in1.IsFixed && in2.IsFixed) { Operand tmp = CreateFixed(in1.Format, in1.ArraySize, Math.MathHelper.Mul(in1.Value, in2.Value)); // We must create a mem copy. compiler.Mov(tmp.Name, outOp.Name); return; } PinFormat dummy; // Special matrix-* or *-matrix multiplication. if (PinFormatHelper.IsMatrix(in1.Format, out dummy) || PinFormatHelper.IsMatrix(in2.Format, out dummy)) { compiler.MulEx(in1.Name, in2.Name, outOp.Name); } else { compiler.Mul(in1.Name, in2.Name, outOp.Name); } }
public SwizzleOperation(SwizzleMask mask) { this.mask = mask; inputDesc = new PinsDescriptor( new PinDescriptor(PinFormatHelper.ContainsComponents(mask.MinimumSwizzleInFormat), "Data to be swizzled.")); }
/// <summary> /// Creates an expand operation. /// </summary> public ExpandOperation(PinFormat expandTo, ExpandType type) { this.type = type; this.expandTo = expandTo; inputDesc = new PinsDescriptor( new PinDescriptor(PinFormatHelper.ExpandableTo(expandTo), "Data to be expanded.")); }
protected override Pin[] CreateOutputs() { PinFormat scalar; PinFormatHelper.IsVector(inputs[0].Format, out scalar); // We now create result. return(new Pin[] { new Pin(scalar, Pin.NotArray, this) }); }
/// <summary> /// Multiplies two operands. /// </summary> public Operand Mul(Operand in1, Operand in2) { // TODO: validation. PinFormat outFmt = in1.Format; // Same format. if (in1.Format == in2.Format) { outFmt = in1.Format; } // Matrix x vector. else if (in1.Format == PinFormat.Float4x4 && in2.Format == PinFormat.Floatx4) { outFmt = PinFormat.Floatx4; } // By scalar. else if (in1.Format == PinFormat.Float) { outFmt = in2.Format; } else if (in2.Format == PinFormat.Float) { outFmt = in1.Format; } else { throw new NotSupportedException(); } // We check if we can precache it, this is copy only op. if (in1.IsFixed && in2.IsFixed) { return(CreateFixed(outFmt, in1.ArraySize, Math.MathHelper.Mul(in1.Value, in2.Value))); } // Else create temp and return. Operand tmp = CreateTemporary(outFmt, in1.ArraySize); PinFormat dummy; // Special matrix-* or *-matrix multiplication. if (PinFormatHelper.IsMatrix(in1.Format, out dummy) || PinFormatHelper.IsMatrix(in2.Format, out dummy)) { compiler.MulEx(in1.Name, in2.Name, tmp.Name); } else { compiler.Mul(in1.Name, in2.Name, tmp.Name); } return(tmp); }
/// <summary> /// Registers parameters of interface. /// </summary> /// <param name="xname"></param> /// <param name="interface"></param> /// <returns></returns> public static ShaderCompiler.Operand[] RegisterInterfaceConstants( ShaderCompiler compiler, string xname, FixedShaderParameters parameters, IInterface @interface) { // We first extract interface parameters and register them ParameterDescription[] descs = @interface.AdditionalParameters; ShaderCompiler.Operand[] constants = new ShaderCompiler.Operand[descs.Length]; for (int j = 0; j < descs.Length; j++) { ParameterDescription desc = descs[j]; string name = string.Format("{0}.{1}", xname, desc.Name); if (desc.IsFixed) { if (PinFormatHelper.IsTexture(desc.Pin.Format)) { // We check the id. uint regId = (uint)parameters[name]; constants[j] = compiler.CreateTexture(desc.Pin.Format, desc.Pin.TextureFormat, regId); } else if (desc.Pin.Format == PinFormat.Sampler) { uint regId = (uint)parameters[name]; constants[j] = compiler.CreateSampler(regId); } else { throw new NotImplementedException("Fixed data not yet implemented."); } } else { uint layoutID; // If it is not fixed, we create constant. uint offset = parameters.GetOffset(name, out layoutID); constants[j] = compiler.CreateConstant(desc.Pin.Format, desc.Pin.Size, layoutID, offset); } } return(constants); }
/// <summary> /// Adds element at specified offset. /// </summary> /// <param name="name">The name of parameter.</param> /// <param name="format">The format of parameter.</param> /// <param name="offset">The offset of element.</param> public void AddElement([NotEmpty] string name, PinFormat format, uint arraySize, uint offset) { // Validate format. PinFormat scalar = PinFormatHelper.ToScalar(format); if (scalar != PinFormat.Integer && scalar != PinFormat.Float) { throw new ArgumentException("Only Float and Integer format acceptable."); } if (data.ContainsKey(name)) { throw new ArgumentException(string.Format("Name {0} is already defined.", name)); } // We add element. ConstantBufferLayout.ParamOffset d = new ConstantBufferLayout.ParamOffset(); d.Description = new ParameterDescription(name, new Pin(format, arraySize, null)); d.Offset = offset; data.Add(name, d); }
/// <summary> /// We check the parameter and do it recursevelly in case of interfaces. /// </summary> /// <param name="parameter"></param> private bool CheckParam(ParameterDescription parameter, out string errorDesc) { errorDesc = null; // We first find it. object value; if (!fixedParameters.TryGetValue(parameter.Name, out value)) { if (parameter.IsFixed) { errorDesc = string.Format("Parameter {0} is not defined in fixed shader parameters and it should be.", parameter.Name); return(false); } // We must locate parameter in one of constant layouts. foreach (ConstantBufferLayout layout in layouts) { if (layout.IsDefined(parameter.Name)) { return(true); } } errorDesc = string.Format("Parameter {0} is not defined anywhere", parameter.Name); return(false); } // We first check if format is compatible and "sizes" are compatible. if (parameter.Pin.IsDynamicArray) { switch (parameter.Pin.Format) { case PinFormat.Texture1D: case PinFormat.Texture1DArray: case PinFormat.Texture2D: case PinFormat.Texture2DArray: case PinFormat.TextureCube: case PinFormat.Texture3D: case PinFormat.BufferTexture: if (value is uint[]) { uint[] array = (uint[])value; for (int i = 0; i < array.Length; i++) { if (array[i] >= GraphicsDevice.MaxTexture) { errorDesc = string.Format("Index of texture must be in range [0,{0}) for all parameter {1}, it is not at least for index {2}", GraphicsDevice.MaxTexture, parameter.Name, i); return(false); } } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint[] that represents position of textures", parameter.Name); return(false); } break; case PinFormat.Sampler: if (value is uint[]) { uint[] array = (uint[])value; for (int i = 0; i < array.Length; i++) { if ((uint)array[i] >= GraphicsDevice.MaxStateObjectsPerType) { errorDesc = string.Format("Index of sampler state must be in range [0,{0}) for parameter {1}, index {2}", GraphicsDevice.MaxTexture, parameter.Name, i); return(false); } } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint that represents positions of samplers", parameter.Name); return(false); } break; case PinFormat.Interface: if (value is IInterface[]) { IInterface[] array = value as IInterface[]; for (int i = 0; i < array.Length; i++) { // We check consistency of interface when compiled (more efficient). foreach (ParameterDescription d in array[i].AdditionalParameters) { // We first "scope" the parameter. ParameterDescription d2 = ParameterDescription.ScopeParameter(parameter.Name, i, d); // Now we search for it (validate it). if (!CheckParam(d2, out errorDesc)) { return(false); } } } } else { errorDesc = string.Format("The parameter {0} is not an interface array. All parameters must be filled in IInterface[] (and not other base type).", parameter.Name); return(false); } break; default: uint arraySize; // For all others, we check type consistency. if (!PinFormatHelper.IsCompatibleArray(parameter.Pin.Format, value, out arraySize)) { errorDesc = string.Format("Array parameter {0} with format {1} is not compatible with value {2}", parameter.Name, parameter.Pin.Format, value); return(false); } // We check if array length is ok. object va; if (fixedParameters.TryGetValue(parameter.Name + ".length", out va) && (va is uint)) { if ((uint)va != arraySize) { errorDesc = string.Format("Array size {0} for parameter {1} needn't be specified, but it is specified and it is {2} - not consistant.", arraySize, parameter.Name, va); return(false); } } break; } } else if (parameter.Pin.IsStaticArray) { switch (parameter.Pin.Format) { case PinFormat.Texture1D: case PinFormat.BufferTexture: case PinFormat.Texture1DArray: case PinFormat.Texture2D: case PinFormat.Texture2DArray: case PinFormat.TextureCube: case PinFormat.Texture3D: if (value is uint[]) { uint[] array = (uint[])value; if (array.Length != parameter.Pin.Size) { errorDesc = string.Format("The length of array of parameter {0} is {1} but should be {2}", parameter.Name, array.Length, parameter.Pin.Size); return(false); } for (int i = 0; i < array.Length; i++) { if (array[i] >= GraphicsDevice.MaxTexture) { errorDesc = string.Format("Index of texture must be in range [0,{0}) for all parameter {1}, it is not at least for index {2}", GraphicsDevice.MaxTexture, parameter.Name, i); return(false); } } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint[] that represents position of textures", parameter.Name); return(false); } break; case PinFormat.Sampler: if (value is uint[]) { uint[] array = (uint[])value; if (array.Length != parameter.Pin.Size) { errorDesc = string.Format("The length of array of parameter {0} is {1} but should be {2}", parameter.Name, array.Length, parameter.Pin.Size); return(false); } for (int i = 0; i < array.Length; i++) { if ((uint)array[i] >= GraphicsDevice.MaxStateObjectsPerType) { errorDesc = string.Format("Index of sampler state must be in range [0,{0}) for parameter {1}, index {2}", GraphicsDevice.MaxTexture, parameter.Name, i); return(false); } } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint that represents positions of samplers", parameter.Name); return(false); } break; case PinFormat.Interface: if (value is IInterface[]) { IInterface[] array = value as IInterface[]; if (array.Length != parameter.Pin.Size) { errorDesc = string.Format("The length of array of parameter {0} is {1} but should be {2}", parameter.Name, array.Length, parameter.Pin.Size); return(false); } for (int i = 0; i < array.Length; i++) { // We check consistency of interface when compiled (more efficient). foreach (ParameterDescription d in array[i].AdditionalParameters) { // We first "scope" the parameter. ParameterDescription d2 = ParameterDescription.ScopeParameter(parameter.Name, d); // Now we search for it (validate it). if (!CheckParam(d2, out errorDesc)) { return(false); } } } } else { errorDesc = string.Format("The parameter {0} is not an interface array. All parameters must be filled in IInterface[] (and not other base type).", parameter.Name); return(false); } break; default: uint arraySize; // For all others, we check type consistency. if (!PinFormatHelper.IsCompatibleArray(parameter.Pin.Format, value, out arraySize)) { errorDesc = string.Format("Array parameter {0} with format {1} is not compatible with value {2}", parameter.Name, parameter.Pin.Format, value); return(false); } // We check if array length is ok. if (arraySize != parameter.Pin.Size) { errorDesc = string.Format("Parameter {0} with array size {1} is expected to be of size {2}", parameter.Name, arraySize, parameter.Pin.Size); return(false); } break; } } else { switch (parameter.Pin.Format) { case PinFormat.Texture1D: case PinFormat.BufferTexture: case PinFormat.Texture1DArray: case PinFormat.Texture2D: case PinFormat.Texture2DArray: case PinFormat.TextureCube: case PinFormat.Texture3D: if (value is uint) { if ((uint)value >= GraphicsDevice.MaxTexture) { errorDesc = string.Format("Index of texture must be in range [0,{0}) for parameter {1}", GraphicsDevice.MaxTexture, parameter.Name); return(false); } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint that represents position of texture", parameter.Name); return(false); } break; case PinFormat.Sampler: if (value is uint) { if ((uint)value >= GraphicsDevice.MaxStateObjectsPerType) { errorDesc = string.Format("Index of sampler state must be in range [0,{0}) for parameter {1}", GraphicsDevice.MaxTexture, parameter.Name); return(false); } } else { errorDesc = string.Format("Value of format for parameter {0} must be uint that represents position of sampler", parameter.Name); return(false); } break; case PinFormat.Interface: if (value is IInterface) { IInterface ivalue = value as IInterface; // We check consistency of interface when compiled (more efficient). foreach (ParameterDescription d in ivalue.AdditionalParameters) { // We first "scope" the parameter. ParameterDescription d2 = ParameterDescription.ScopeParameter(parameter.Name, d); // Now we search for it (validate it). if (!CheckParam(d2, out errorDesc)) { return(false); } } } else { errorDesc = string.Format("The parameter {0} is not an interface (does not extend IInterface)", parameter.Name); return(false); } break; default: // For all others, we check type consistency. if (!PinFormatHelper.IsCompatible(parameter.Pin.Format, value)) { errorDesc = string.Format("Parameter {0} with format {1} is not compatible with value {2}", parameter.Name, parameter.Pin.Format, value); return(false); } break; } } return(true); }
/// <summary> /// Appends element to format. /// </summary> /// <param name="name"></param> /// <param name="format"></param> public void AppendElement([NotEmpty] string name, PinFormat format, uint arraySize) { currentOffset = PinFormatHelper.Align(format, currentOffset); AddElement(name, format, Pin.NotArray, currentOffset); currentOffset += PinFormatHelper.Advance(format, arraySize); }