Exemple #1
0
        private static int ComputeMemberSize(ref EffectParameterValueData member, ref int constantBufferOffset)
        {
            var elementSize = ComputeTypeSize(member.Param.Type);
            int size;
            int alignment;

            switch (member.Param.Class)
            {
            case EffectParameterClass.Scalar:
            {
                size      = elementSize;
                alignment = size;
                break;
            }

            case EffectParameterClass.Color:
            case EffectParameterClass.Vector:
            {
                size      = elementSize * member.ColumnCount;
                alignment = (member.ColumnCount == 3 ? 4 : member.ColumnCount) * elementSize;         // vec3 uses alignment of vec4
                break;
            }

            case EffectParameterClass.MatrixColumns:
            {
                size      = elementSize * 4 * member.ColumnCount;
                alignment = size;
                break;
            }

            case EffectParameterClass.MatrixRows:
            {
                size      = elementSize * 4 * member.RowCount;
                alignment = size;
                break;
            }

            default:
                throw new NotImplementedException();
            }

            // Array
            if (member.Count > 0)
            {
                var roundedSize = (size + 15) / 16 * 16; // Round up to vec4
                size      = roundedSize * member.Count;
                alignment = roundedSize * member.Count;
            }

            // Alignment is maxed up to vec4
            if (alignment > 16)
            {
                alignment = 16;
            }

            // Align offset and store it as member offset
            constantBufferOffset = (constantBufferOffset + alignment - 1) / alignment * alignment;

            return(size);
        }
Exemple #2
0
        private static int ComputeMemberSize(ref EffectParameterValueData member, ref int constantBufferOffset)
        {
            var elementSize = ComputeTypeSize(member.Param.Type);
            int size;
            int alignment = 4;

            switch (member.Param.Class)
            {
            case EffectParameterClass.Scalar:
            {
                size = elementSize;
                break;
            }

            case EffectParameterClass.Color:
            case EffectParameterClass.Vector:
            {
                size = elementSize * member.ColumnCount;
                break;
            }

            case EffectParameterClass.MatrixColumns:
            {
                size = elementSize * (4 * (member.ColumnCount - 1) + member.RowCount);
                break;
            }

            case EffectParameterClass.MatrixRows:
            {
                size = elementSize * (4 * (member.RowCount - 1) + member.ColumnCount);
                break;
            }

            default:
                throw new NotImplementedException();
            }

            // Array
            if (member.Count > 0)
            {
                var roundedSize = (size + 15) / 16 * 16; // Round up to vec4
                size     += roundedSize * (member.Count - 1);
                alignment = 16;
            }

            // Align to float4 if it is bigger than leftover space in current float4
            if (constantBufferOffset / 16 != (constantBufferOffset + size - 1) / 16)
            {
                alignment = 16;
            }

            // Align offset and store it as member offset
            constantBufferOffset = (constantBufferOffset + alignment - 1) / alignment * alignment;

            return(size);
        }
Exemple #3
0
        private void LinkConstant(string cbName, Variable variable, LocalParameterKey parameterKey)
        {
            // If the constant buffer is not present, add it
            var constantBuffer = effectReflection.ConstantBuffers.FirstOrDefault(buffer => buffer.Name == cbName);

            if (constantBuffer == null)
            {
                constantBuffer = new ShaderConstantBufferDescription()
                {
                    Name = cbName, Type = ConstantBufferType.ConstantBuffer
                };
                effectReflection.ConstantBuffers.Add(constantBuffer);
                var constantBufferBinding = new EffectParameterResourceData {
                    Param = { KeyName = cbName, Class = EffectParameterClass.ConstantBuffer, Type = EffectParameterType.Buffer, RawName = cbName, ResourceGroup = cbName }, SlotStart = -1, SlotCount = 1
                };
                effectReflection.ResourceBindings.Add(constantBufferBinding);
                valueBindings.Add(constantBuffer, new List <EffectParameterValueData>());
            }

            // Get the list of members of this constant buffer
            var members = valueBindings[constantBuffer];

            var binding = new EffectParameterValueData
            {
                Param =
                {
                    KeyName = parameterKey.Name,
                    Class   = parameterKey.Class,
                    Type    = parameterKey.Type,
                    RawName = variable.Name
                },
                RowCount    = parameterKey.RowCount,
                ColumnCount = parameterKey.ColumnCount,
                Count       = parameterKey.Count,
            };

            members.Add(binding);
        }
Exemple #4
0
        private ShaderConstantBufferDescription GetConstantBufferReflection(ConstantBuffer constantBufferRaw, ref ConstantBufferDescription constantBufferRawDesc, ShaderConstantBufferDescription linkBuffer, LoggerResult log)
        {
            var constantBuffer = new ShaderConstantBufferDescription
            {
                Name = constantBufferRawDesc.Name,
                Size = constantBufferRawDesc.Size,
            };

            switch (constantBufferRawDesc.Type)
            {
                case SharpDX.D3DCompiler.ConstantBufferType.ConstantBuffer:
                    constantBuffer.Type = ConstantBufferType.ConstantBuffer;
                    break;
                case SharpDX.D3DCompiler.ConstantBufferType.TextureBuffer:
                    constantBuffer.Type = ConstantBufferType.TextureBuffer;
                    break;
                default:
                    constantBuffer.Type = ConstantBufferType.Unknown;
                    break;
            }

            // ConstantBuffers variables
            var members = new List<EffectParameterValueData>();
            for (int i = 0; i < constantBufferRawDesc.VariableCount; i++)
            {
                var variable = constantBufferRaw.GetVariable(i);
                var variableType = variable.GetVariableType();
                var variableDescription = variable.Description;
                var variableTypeDescription = variableType.Description;

                var parameter = new EffectParameterValueData()
                {
                    Param =
                    {
                        Class = (EffectParameterClass)variableTypeDescription.Class,
                        Type = ConvertVariableValueType(variableTypeDescription.Type, log),
                        RawName = variableDescription.Name,
                    },
                    Offset = variableDescription.StartOffset,
                    Size = variableDescription.Size,
                    Count = variableTypeDescription.ElementCount == 0 ? 1 : variableTypeDescription.ElementCount,
                    RowCount = (byte)variableTypeDescription.RowCount,
                    ColumnCount = (byte)variableTypeDescription.ColumnCount,
                };

                if (variableTypeDescription.Offset != 0)
                {
                    log.Error("Unexpected offset [{0}] for variable [{1}] in constant buffer [{2}]", variableTypeDescription.Offset, variableDescription.Name, constantBuffer.Name);
                }

                bool bindingNotFound = true;
                // Retrieve Link Member
                foreach (var binding in linkBuffer.Members)
                {
                    if (binding.Param.RawName == variableDescription.Name)
                    {
                        // TODO: should we replicate linkMember.Count/RowCount/ColumnCount? or use what is retrieved by D3DCompiler reflection
                        parameter.Param.KeyName = binding.Param.KeyName;
                        bindingNotFound = false;
                        break;
                    }
                }

                if (bindingNotFound)
                {
                    log.Error("Variable [{0}] in constant buffer [{1}] has no link", variableDescription.Name, constantBuffer.Name);
                }

                members.Add(parameter);
            }
            constantBuffer.Members = members.ToArray();

            return constantBuffer;
        }
Exemple #5
0
        private unsafe bool UpdateValue(ShaderParameterUpdater parameterUpdater, ref EffectParameterValueData shaderVariable, int i)
        {
            if (shaderVariable.Param.KeyIndex == -1)
            {
                throw new InvalidOperationException();
            }

            BoundConstantBufferParam paramReference = constantBufferParams[i];

            var internalValue = parameterUpdater.GetInternalValue(shaderVariable.Param.KeyIndex);

            // TODO: Comparing Counter+DataPointer is not enough (if realloc on same address)
            if (internalValue.Counter == paramReference.DirtyCount &&
                internalValue == paramReference.DataPointer)
            {
                return(false);
            }

            constantBufferParams[i] = new BoundConstantBufferParam
            {
                DataPointer = internalValue,
                DirtyCount  = internalValue.Counter
            };

            var destination = (byte *)(Data + shaderVariable.Offset);

            int sourceOffset = 0;

            float *variableData = (float *)destination; // + shaderVariable.Offset);

            Matrix tempMatrix;

            switch (shaderVariable.Param.Class)
            {
            case EffectParameterClass.Struct:
                internalValue.ReadFrom((IntPtr)variableData, sourceOffset, shaderVariable.Size);
                break;

            case EffectParameterClass.Scalar:
                for (int elt = 0; elt < shaderVariable.Count; ++elt)
                {
                    internalValue.ReadFrom((IntPtr)variableData, sourceOffset, sizeof(float));
                    //*variableData = *source++;
                    sourceOffset += 4;
                    variableData += 4;     // 4 floats
                }
                break;

            case EffectParameterClass.Vector:
            case EffectParameterClass.Color:
                for (int elt = 0; elt < shaderVariable.Count; ++elt)
                {
                    //Framework.Utilities.CopyMemory((IntPtr)variableData, (IntPtr)source, (int)(shaderVariable.ColumnCount * sizeof(float)));
                    internalValue.ReadFrom((IntPtr)variableData, sourceOffset, (int)(shaderVariable.ColumnCount * sizeof(float)));
                    sourceOffset += (int)shaderVariable.ColumnCount * 4;
                    variableData += 4;
                }
                break;

            case EffectParameterClass.MatrixColumns:
                for (int elt = 0; elt < shaderVariable.Count; ++elt)
                {
                    //fixed (Matrix* p = &tempMatrix)
                    {
                        internalValue.ReadFrom((IntPtr)(byte *)&tempMatrix, sourceOffset, (int)(shaderVariable.ColumnCount * shaderVariable.RowCount * sizeof(float)));
                        ((Matrix *)variableData)->CopyMatrixFrom((float *)&tempMatrix, unchecked ((int)shaderVariable.ColumnCount), unchecked ((int)shaderVariable.RowCount));
                        sourceOffset += (int)(shaderVariable.ColumnCount * shaderVariable.RowCount) * 4;
                        variableData += 4 * shaderVariable.RowCount;
                    }
                }
                break;

            case EffectParameterClass.MatrixRows:
                for (int elt = 0; elt < shaderVariable.Count; ++elt)
                {
                    //fixed (Matrix* p = &tempMatrix)
                    {
                        internalValue.ReadFrom((IntPtr)(byte *)&tempMatrix, sourceOffset, (int)(shaderVariable.ColumnCount * shaderVariable.RowCount * sizeof(float)));
                        ((Matrix *)variableData)->TransposeMatrixFrom((float *)&tempMatrix, unchecked ((int)shaderVariable.ColumnCount), unchecked ((int)shaderVariable.RowCount));
                        //source += shaderVariable.ColumnCount * shaderVariable.RowCount;
                        sourceOffset += (int)(shaderVariable.ColumnCount * shaderVariable.RowCount) * 4;
                        variableData += 4 * shaderVariable.RowCount;
                    }
                }
                break;
            }

            return(true);
        }
Exemple #6
0
        private ShaderConstantBufferDescription GetConstantBufferReflection(ConstantBuffer constantBufferRaw, ref ConstantBufferDescription constantBufferRawDesc, ShaderConstantBufferDescription linkBuffer, LoggerResult log)
        {
            var constantBuffer = new ShaderConstantBufferDescription
            {
                Name = constantBufferRawDesc.Name,
                Size = constantBufferRawDesc.Size,
            };

            switch (constantBufferRawDesc.Type)
            {
                case SharpDX.D3DCompiler.ConstantBufferType.ConstantBuffer:
                    constantBuffer.Type = ConstantBufferType.ConstantBuffer;
                    break;
                case SharpDX.D3DCompiler.ConstantBufferType.TextureBuffer:
                    constantBuffer.Type = ConstantBufferType.TextureBuffer;
                    break;
                default:
                    constantBuffer.Type = ConstantBufferType.Unknown;
                    break;
            }

            // ConstantBuffers variables
            var members = new List<EffectParameterValueData>();
            for (int i = 0; i < constantBufferRawDesc.VariableCount; i++)
            {
                var variable = constantBufferRaw.GetVariable(i);
                var variableType = variable.GetVariableType();
                var variableDescription = variable.Description;
                var variableTypeDescription = variableType.Description;

                var parameter = new EffectParameterValueData()
                {
                    Param =
                    {
                        Class = (EffectParameterClass)variableTypeDescription.Class,
                        Type = ConvertVariableValueType(variableTypeDescription.Type, log),
                        RawName = variableDescription.Name,
                    },
                    Offset = variableDescription.StartOffset,
                    Size = variableDescription.Size,
                    Count = variableTypeDescription.ElementCount == 0 ? 1 : variableTypeDescription.ElementCount,
                    RowCount = (byte)variableTypeDescription.RowCount,
                    ColumnCount = (byte)variableTypeDescription.ColumnCount,
                };

                if (variableTypeDescription.Offset != 0)
                {
                    log.Error("Unexpected offset [{0}] for variable [{1}] in constant buffer [{2}]", variableTypeDescription.Offset, variableDescription.Name, constantBuffer.Name);
                }

                bool bindingNotFound = true;
                // Retrieve Link Member
                foreach (var binding in linkBuffer.Members)
                {
                    if (binding.Param.RawName == variableDescription.Name)
                    {
                        // TODO: should we replicate linkMember.Count/RowCount/ColumnCount? or use what is retrieved by D3DCompiler reflection
                        parameter.Param.KeyName = binding.Param.KeyName;
                        bindingNotFound = false;
                        break;
                    }
                }

                if (bindingNotFound)
                {
                    log.Error("Variable [{0}] in constant buffer [{1}] has no link", variableDescription.Name, constantBuffer.Name);
                }

                members.Add(parameter);
            }
            constantBuffer.Members = members.ToArray();

            return constantBuffer;
        }
Exemple #7
0
        private void LinkConstant(string cbName, Variable variable, LocalParameterKey parameterKey)
        {
            // If the constant buffer is not present, add it
            var constantBuffer = effectReflection.ConstantBuffers.FirstOrDefault(buffer => buffer.Name == cbName);
            if (constantBuffer == null)
            {
                constantBuffer = new ShaderConstantBufferDescription() {Name = cbName};
                effectReflection.ConstantBuffers.Add(constantBuffer);
                var constantBufferBinding = new EffectParameterResourceData { Param = { KeyName = cbName, Class = EffectParameterClass.ConstantBuffer, Type = EffectParameterType.Buffer, RawName = cbName }, SlotStart = -1 };
                effectReflection.ResourceBindings.Add(constantBufferBinding);
                valueBindings.Add(constantBuffer, new List<EffectParameterValueData>());
            }

            // Get the list of members of this constant buffer
            var members = valueBindings[constantBuffer];

            var binding = new EffectParameterValueData
                {
                    Param =
                        {
                            KeyName = parameterKey.Name,
                            Class = parameterKey.Class,
                            Type = parameterKey.Type,
                            RawName = variable.Name
                        },
                    RowCount = parameterKey.RowCount,
                    ColumnCount = parameterKey.ColumnCount,
                    Count = parameterKey.Count,
                };
            
            members.Add(binding);
        }
Exemple #8
0
        private static ParameterKey FindOrCreateValueKey <T>(EffectParameterValueData binding) where T : struct
        {
            var name = binding.Param.KeyName;

            return(ParameterKeys.FindByName(name) ?? ParameterKeys.NewValue <T>(default(T), name));
        }
Exemple #9
0
        private static void UpdateValueBindingKey(ref EffectParameterValueData binding)
        {
            switch (binding.Param.Class)
            {
            case EffectParameterClass.Scalar:
                switch (binding.Param.Type)
                {
                case EffectParameterType.Bool:
                    binding.Param.Key = FindOrCreateValueKey <bool>(binding);
                    break;

                case EffectParameterType.Int:
                    binding.Param.Key = FindOrCreateValueKey <int>(binding);
                    break;

                case EffectParameterType.UInt:
                    binding.Param.Key = FindOrCreateValueKey <uint>(binding);
                    break;

                case EffectParameterType.Float:
                    binding.Param.Key = FindOrCreateValueKey <float>(binding);
                    break;
                }
                break;

            case EffectParameterClass.Color:
            {
                var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
                switch (binding.Param.Type)
                {
                case EffectParameterType.Float:
                    binding.Param.Key = componentCount == 4
                                                        ? FindOrCreateValueKey <Color4>(binding)
                                                        : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey <Color3>(binding) : null);
                    break;
                }
            }
            break;

            case EffectParameterClass.Vector:
            {
                var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
                switch (binding.Param.Type)
                {
                case EffectParameterType.Bool:
                case EffectParameterType.Int:
                    binding.Param.Key = componentCount == 4 ? (ParameterKey)FindOrCreateValueKey <Int4>(binding) : (componentCount == 3 ? FindOrCreateValueKey <Int3>(binding) : null);
                    break;

                case EffectParameterType.UInt:
                    binding.Param.Key = componentCount == 4 ? FindOrCreateValueKey <UInt4>(binding) : null;
                    break;

                case EffectParameterType.Float:
                    binding.Param.Key = componentCount == 4
                                                        ? FindOrCreateValueKey <Vector4>(binding)
                                                        : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey <Vector3>(binding) : (componentCount == 2 ? FindOrCreateValueKey <Vector2>(binding) : null));
                    break;
                }
            }
            break;

            case EffectParameterClass.MatrixRows:
            case EffectParameterClass.MatrixColumns:
                binding.Param.Key = FindOrCreateValueKey <Matrix>(binding);
                break;

            case EffectParameterClass.Struct:
                binding.Param.Key = ParameterKeys.FindByName(binding.Param.KeyName);
                break;
            }

            if (binding.Param.Key == null)
            {
                throw new InvalidOperationException(string.Format("Unable to find/generate key [{0}] with unsupported type [{1}/{2}]", binding.Param.KeyName, binding.Param.Class, binding.Param.Type));
            }
        }
Exemple #10
0
        private ParameterKey FindOrCreateValueKey <T>(EffectParameterValueData binding) where T : struct
        {
            var name = binding.Param.KeyName;

            return(ParameterKeys.FindByName(name) ?? (binding.Count > 1 ? (ParameterKey)ParameterKeys.New <T[]>(name) : ParameterKeys.New <T>(name)));
        }
Exemple #11
0
        private ParameterKey UpdateValueBindingKey(ref EffectParameterValueData binding)
        {
            switch (binding.Param.Class)
            {
            case EffectParameterClass.Scalar:
                switch (binding.Param.Type)
                {
                case EffectParameterType.Bool:
                    binding.Param.Key = FindOrCreateValueKey <bool>(binding);
                    break;

                case EffectParameterType.Int:
                    binding.Param.Key = FindOrCreateValueKey <int>(binding);
                    break;

                case EffectParameterType.UInt:
                    binding.Param.Key = FindOrCreateValueKey <uint>(binding);
                    break;

                case EffectParameterType.Float:
                    binding.Param.Key = FindOrCreateValueKey <float>(binding);
                    break;
                }
                break;

            case EffectParameterClass.Color:
            {
                var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
                switch (binding.Param.Type)
                {
                case EffectParameterType.Float:
                    binding.Param.Key = componentCount == 4
                                                        ? FindOrCreateValueKey <Color4>(binding)
                                                        : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey <Color3>(binding) : null);
                    break;
                }
            }
            break;

            case EffectParameterClass.Vector:
            {
                var componentCount = binding.RowCount != 1 ? binding.RowCount : binding.ColumnCount;
                switch (binding.Param.Type)
                {
                case EffectParameterType.Bool:
                case EffectParameterType.Int:
                    binding.Param.Key = componentCount == 4 ? (ParameterKey)FindOrCreateValueKey <Int4>(binding) : (componentCount == 3 ? FindOrCreateValueKey <Int3>(binding) : null);
                    break;

                case EffectParameterType.UInt:
                    binding.Param.Key = componentCount == 4 ? FindOrCreateValueKey <UInt4>(binding) : null;
                    break;

                case EffectParameterType.Float:
                    binding.Param.Key = componentCount == 4
                                                        ? FindOrCreateValueKey <Vector4>(binding)
                                                        : (componentCount == 3 ? (ParameterKey)FindOrCreateValueKey <Vector3>(binding) : (componentCount == 2 ? FindOrCreateValueKey <Vector2>(binding) : null));
                    break;
                }
            }
            break;

            case EffectParameterClass.MatrixRows:
            case EffectParameterClass.MatrixColumns:
                binding.Param.Key = FindOrCreateValueKey <Matrix>(binding);
                break;

            case EffectParameterClass.Struct:
                binding.Param.Key = ParameterKeys.FindByName(binding.Param.KeyName);
                break;
            }

            if (binding.Param.Key == null)
            {
                throw new InvalidOperationException(string.Format("Unable to find/generate key [{0}] with unsupported type [{1}/{2}]", binding.Param.KeyName, binding.Param.Class, binding.Param.Type));
            }

            if (binding.Count > 1)
            {
                // Unspecified array length: guess from shader and set default parameter with array matching shader size
                binding.Param.Key = binding.Param.Key.CloneLength(binding.Count);
            }

            return(binding.Param.Key);
        }
Exemple #12
0
        private void ValidateConstantBufferReflection(ConstantBuffer constantBufferRaw, ref ConstantBufferDescription constantBufferRawDesc, ShaderConstantBufferDescription constantBuffer, LoggerResult log)
        {
            switch (constantBufferRawDesc.Type)
            {
            case SharpDX.D3DCompiler.ConstantBufferType.ConstantBuffer:
                if (constantBuffer.Type != ConstantBufferType.ConstantBuffer)
                {
                    log.Error($"Invalid buffer type for {constantBuffer.Name}: {constantBuffer.Type} instead of {ConstantBufferType.ConstantBuffer}");
                }
                break;

            case SharpDX.D3DCompiler.ConstantBufferType.TextureBuffer:
                if (constantBuffer.Type != ConstantBufferType.TextureBuffer)
                {
                    log.Error($"Invalid buffer type for {constantBuffer.Name}: {constantBuffer.Type} instead of {ConstantBufferType.TextureBuffer}");
                }
                break;

            default:
                if (constantBuffer.Type != ConstantBufferType.Unknown)
                {
                    log.Error($"Invalid buffer type for {constantBuffer.Name}: {constantBuffer.Type} instead of {ConstantBufferType.Unknown}");
                }
                break;
            }

            // ConstantBuffers variables
            for (int i = 0; i < constantBufferRawDesc.VariableCount; i++)
            {
                var variable                = constantBufferRaw.GetVariable(i);
                var variableType            = variable.GetVariableType();
                var variableDescription     = variable.Description;
                var variableTypeDescription = variableType.Description;

                if (variableTypeDescription.Offset != 0)
                {
                    log.Error("Unexpected offset [{0}] for variable [{1}] in constant buffer [{2}]", variableTypeDescription.Offset, variableDescription.Name, constantBuffer.Name);
                }

                var binding = constantBuffer.Members[i];
                // Retrieve Link Member
                if (binding.Param.RawName != variableDescription.Name)
                {
                    log.Error("Variable [{0}] in constant buffer [{1}] has no link", variableDescription.Name, constantBuffer.Name);
                }
                else
                {
                    var parameter = new EffectParameterValueData()
                    {
                        Param =
                        {
                            Class   = (EffectParameterClass)variableTypeDescription.Class,
                            Type    = ConvertVariableValueType(variableTypeDescription.Type, log),
                            RawName = variableDescription.Name,
                        },
                        Offset      = variableDescription.StartOffset,
                        Size        = variableDescription.Size,
                        Count       = variableTypeDescription.ElementCount,
                        RowCount    = (byte)variableTypeDescription.RowCount,
                        ColumnCount = (byte)variableTypeDescription.ColumnCount,
                    };

                    if (parameter.Offset != binding.Offset ||
                        parameter.Size != binding.Size ||
                        parameter.Count != binding.Count ||
                        parameter.RowCount != binding.RowCount ||
                        parameter.ColumnCount != binding.ColumnCount)
                    {
                        log.Error("Variable [{0}] in constant buffer [{1}] binding doesn't match what was expected", variableDescription.Name, constantBuffer.Name);
                    }
                }
            }
            if (constantBuffer.Size != constantBufferRawDesc.Size)
            {
                log.Error($"Error precomputing buffer size for {constantBuffer.Name}: {constantBuffer.Size} instead of {constantBufferRawDesc.Size}");
            }
        }