示例#1
0
        private void UpdateConstantBufferReflection(EffectConstantBufferDescription reflectionConstantBuffer)
        {
            // Used to compute constant buffer size and member offsets (std140 rule)
            int constantBufferOffset = 0;

            // Fill members
            for (int index = 0; index < reflectionConstantBuffer.Members.Length; index++)
            {
                var member = reflectionConstantBuffer.Members[index];

                // Properly compute size and offset according to DX rules
                var memberSize = ComputeMemberSize(ref member.Type, ref constantBufferOffset);

                // Store size/offset info
                member.Offset = constantBufferOffset;
                member.Size   = memberSize;

                // Adjust offset for next item
                constantBufferOffset += memberSize;

                reflectionConstantBuffer.Members[index] = member;
            }

            // Round buffer size to next multiple of 16
            reflectionConstantBuffer.Size = (constantBufferOffset + 15) / 16 * 16;
        }
示例#2
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 EffectConstantBufferDescription()
                {
                    Name = cbName, Type = ConstantBufferType.ConstantBuffer
                };
                effectReflection.ConstantBuffers.Add(constantBuffer);
                var constantBufferBinding = new EffectResourceBindingDescription {
                    KeyInfo = { KeyName = cbName }, Class = EffectParameterClass.ConstantBuffer, Type = EffectParameterType.ConstantBuffer, RawName = cbName, SlotStart = -1, SlotCount = 1, ResourceGroup = cbName
                };
                effectReflection.ResourceBindings.Add(constantBufferBinding);
                valueBindings.Add(constantBuffer, new List <EffectValueDescription>());
            }

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

            var binding = new EffectValueDescription
            {
                KeyInfo =
                {
                    KeyName = parameterKey.Name,
                },
                LogicalGroup = (string)variable.GetTag(XenkoTags.LogicalGroup),
                Type         = parameterKey.Type,
                RawName      = variable.Name,
            };

            members.Add(binding);
        }
示例#3
0
        public ResourceGroupDescription(DescriptorSetLayoutBuilder descriptorSetLayout, EffectConstantBufferDescription constantBufferReflection) : this()
        {
            DescriptorSetLayout      = descriptorSetLayout;
            ConstantBufferReflection = constantBufferReflection;

            // We combine both hash for DescriptorSet and cbuffer itself (if it exists)
            Hash = descriptorSetLayout.Hash;
            if (constantBufferReflection != null)
            {
                ObjectId.Combine(ref Hash, ref constantBufferReflection.Hash, out Hash);
            }
        }
示例#4
0
        public EffectParameterUpdaterLayout(GraphicsDevice graphicsDevice, Effect effect, DescriptorSetLayoutBuilder[] layouts)
        {
            Layouts = layouts;

            // Process constant buffers
            ResourceGroupLayouts = new ResourceGroupLayout[layouts.Length];
            for (int layoutIndex = 0; layoutIndex < layouts.Length; layoutIndex++)
            {
                var layout = layouts[layoutIndex];
                if (layout == null)
                {
                    continue;
                }

                ParameterCollectionLayout.ProcessResources(layout);

                EffectConstantBufferDescription cbuffer = null;

                for (int entryIndex = 0; entryIndex < layout.Entries.Count; ++entryIndex)
                {
                    var layoutEntry = layout.Entries[entryIndex];
                    if (layoutEntry.Class == EffectParameterClass.ConstantBuffer)
                    {
                        // For now we assume first cbuffer will be the main one
                        if (cbuffer == null)
                        {
                            cbuffer = effect.Bytecode.Reflection.ConstantBuffers.First(x => x.Name == layoutEntry.Key.Name);
                            ParameterCollectionLayout.ProcessConstantBuffer(cbuffer);
                        }
                    }
                }

                var resourceGroupDescription = new ResourceGroupDescription(layout, cbuffer);

                ResourceGroupLayouts[layoutIndex] = ResourceGroupLayout.New(graphicsDevice, resourceGroupDescription, effect.Bytecode);
            }
        }
示例#5
0
 public static void ProcessConstantBuffer(this ParameterCollectionLayout parameterCollectionLayout, EffectConstantBufferDescription constantBuffer)
 {
     foreach (var member in constantBuffer.Members)
     {
         parameterCollectionLayout.LayoutParameterKeyInfos.Add(new ParameterKeyInfo(member.KeyInfo.Key, parameterCollectionLayout.BufferSize + member.Offset, member.Type.Elements > 0 ? member.Type.Elements : 1));
     }
     parameterCollectionLayout.BufferSize += constantBuffer.Size;
 }
示例#6
0
        private void ValidateConstantBufferReflection(ConstantBuffer constantBufferRaw, ref ConstantBufferDescription constantBufferRawDesc, EffectConstantBufferDescription 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 [{variableTypeDescription.Offset}] for variable [{variableDescription.Name}] in constant buffer [{constantBuffer.Name}]");
                }

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

                    if (parameter.Offset != binding.Offset ||
                        parameter.Size != binding.Size ||
                        parameter.Type.Elements != binding.Type.Elements ||
                        ((parameter.Type.Class != EffectParameterClass.Struct) &&    // Ignore columns/rows if it's a struct (sometimes it contains weird data)
                         (parameter.Type.RowCount != binding.Type.RowCount || parameter.Type.ColumnCount != binding.Type.ColumnCount)))
                    {
                        log.Error($"Variable [{variableDescription.Name}] in constant buffer [{constantBuffer.Name}] binding doesn't match what was expected");
                    }
                }
            }
            if (constantBuffer.Size != constantBufferRawDesc.Size)
            {
                log.Error($"Error precomputing buffer size for {constantBuffer.Name}: {constantBuffer.Size} instead of {constantBufferRawDesc.Size}");
            }
        }
示例#7
0
        private void AddUniform(EffectReflection effectReflection, bool[] validConstantBuffers, int uniformSize, int uniformCount, string uniformName, ActiveUniformType uniformType)
        {
            // OpenGL ES 2 is adding uniform for each cbuffer member, so we need to remove array and struct indexers so that we can identify it in cbuffer and find offset
            var uniformParts     = new List <UniformPart>(8);
            var uniformLastStart = 0;

            for (var index = 0; index <= uniformName.Length; index++)
            {
                char c = index == uniformName.Length ? '.' : uniformName[index]; // Treat string end same as '.'
                if (c == '.' || c == '[')
                {
                    var uniformPart = new UniformPart {
                        Start = uniformLastStart, Count = index - uniformLastStart, Indexer = -1
                    };

                    // Read array index (if any)
                    if (c == '[')
                    {
                        var indexerStart = ++index;
                        while (uniformName[index] != ']')
                        {
                            index++;
                        }
                        // TODO: Avoid substring
                        uniformPart.Indexer = int.Parse(uniformName.Substring(indexerStart, index - indexerStart));
                        index++;
                    }

                    uniformParts.Add(uniformPart);
                    uniformLastStart = index + 1;
                }
            }

            var variableName = uniformName.Substring(0, uniformParts[0].Count);

            // check that this uniform is in a constant buffer
            int indexOfConstantBuffer = -1;
            int indexOfMember         = -1;
            EffectConstantBufferDescription constantBufferDescription = null;

            for (int cbIndex = 0; cbIndex < effectReflection.ConstantBuffers.Count; cbIndex++)
            {
                var currentConstantBuffer = effectReflection.ConstantBuffers[cbIndex];
                for (int index = 0; index < currentConstantBuffer.Members.Length; index++)
                {
                    var member = currentConstantBuffer.Members[index];
                    if (member.RawName.Equals(variableName))
                    {
                        indexOfConstantBuffer     = cbIndex;
                        indexOfMember             = index;
                        constantBufferDescription = currentConstantBuffer;
                        break;
                    }
                }
                if (constantBufferDescription != null)
                {
                    break;
                }
            }

            if (constantBufferDescription == null)
            {
                throw new Exception("The uniform value " + variableName + " is defined outside of a uniform block, which is not supported by the engine.");
            }

            var indexOfResource = effectReflection.ResourceBindings.FindIndex(x => x.RawName == constantBufferDescription.Name);

            if (indexOfResource == -1)
            {
                reflectionResult.Error($"Unable to find uniform [{uniformName}] in any constant buffer");
                return;
            }

            //var constantBufferDescription = effectReflection.ConstantBuffers[indexOfConstantBufferDescription];
            var constantBuffer = effectReflection.ResourceBindings[indexOfResource];

            // First time we encounter this cbuffer?
            if (!validConstantBuffers[indexOfConstantBuffer])
            {
                constantBuffer.SlotStart = ConstantBufferOffsets.Length - 1;

                // Find next cbuffer slot
                Array.Resize(ref ConstantBufferOffsets, ConstantBufferOffsets.Length + 1);

                effectReflection.ResourceBindings[indexOfResource] = constantBuffer;

                ConstantBufferOffsets[constantBuffer.SlotStart + 1] = ConstantBufferOffsets[constantBuffer.SlotStart] + constantBufferDescription.Size;

                validConstantBuffers[indexOfConstantBuffer] = true;
            }

            //var elementSize = uniformSize;

            // For array, each element is rounded to register size
            //if (uniformSize%16 != 0 && uniformCount > 1)
            //{
            //    constantBufferDescription.Size = (constantBufferDescription.Size + 15)/16*16;
            //    uniformSize = (uniformSize + 15)/16*16;
            //}

            // Check if it can fits in the same register, otherwise starts at the next one
            //if (uniformCount == 1 && constantBufferDescription.Size/16 != (constantBufferDescription.Size + uniformSize - 1)/16)
            //    constantBufferDescription.Size = (constantBufferDescription.Size + 15)/16*16;

            var variable = constantBufferDescription.Members[indexOfMember];

            // Resolve array/member
            var offset = variable.Offset;
            var type   = variable.Type;

            for (int i = 0; i < uniformParts.Count; ++i)
            {
                var uniformPart = uniformParts[i];

                // Apply member
                if (i > 0)
                {
                    if (type.Members == null)
                    {
                        throw new InvalidOperationException($"Tried to find member \"{uniformName.Substring(uniformPart.Start, uniformPart.Count)}\" on a non-struct type when processing \"{uniformName}\"");
                    }

                    bool memberFound = false;
                    for (int memberIndex = 0; memberIndex < type.Members.Length; ++memberIndex)
                    {
                        var member = type.Members[memberIndex];
                        if (string.Compare(member.Name, 0, uniformName, uniformPart.Start, uniformPart.Count) == 0)
                        {
                            // Adjust offset and set new type
                            offset += member.Offset;
                            type    = member.Type;

                            memberFound = true;
                            break;
                        }
                    }

                    if (!memberFound)
                    {
                        throw new InvalidOperationException($"Couldn't find member \"{uniformName.Substring(uniformPart.Start, uniformPart.Count)}\" on struct type \"{type.Name}\" when processing \"{uniformName}\"");
                    }
                }

                // Apply indexer for arrays
                if (uniformPart.Indexer != -1)
                {
                    offset += (type.ElementSize + 15) / 16 * 16 * uniformPart.Indexer;
                }
            }

            // Check type
            if (type.Type != GetTypeFromActiveUniformType(uniformType))
            {
                throw new InvalidOperationException($"Uniform [{uniformName}] of type [{variable.Type.Type}] doesn't match OpenGL shader expected type [{GetTypeFromActiveUniformType(uniformType)}]");
            }

            // No need to compare last element padding.
            // TODO: In case of float1/float2 arrays (rare) it is quite non-optimal to do a CompareMemory
            //variable.Size = uniformSize * (uniformCount - 1) + elementSize;
            //constantBufferDescription.Members[indexOfUniform] = variable;

            Uniforms.Add(new Uniform
            {
                Type               = uniformType,
                Count              = uniformCount,
                CompareSize        = uniformSize + (uniformSize + 15) / 16 * 16 * (uniformCount - 1),
                ConstantBufferSlot = constantBuffer.SlotStart,
                Offset             = offset,
                UniformIndex       = GL.GetUniformLocation(ProgramId, uniformName)
            });
        }
示例#8
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 EffectConstantBufferDescription() {Name = cbName, Type = ConstantBufferType.ConstantBuffer};
                effectReflection.ConstantBuffers.Add(constantBuffer);
                var constantBufferBinding = new EffectResourceBindingDescription { KeyInfo = { KeyName = cbName }, Class = EffectParameterClass.ConstantBuffer, Type = EffectParameterType.ConstantBuffer, RawName = cbName, SlotStart = -1, SlotCount = 1, ResourceGroup = cbName };
                effectReflection.ResourceBindings.Add(constantBufferBinding);
                valueBindings.Add(constantBuffer, new List<EffectValueDescription>());
            }

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

            var binding = new EffectValueDescription
            {
                KeyInfo =
                {
                    KeyName = parameterKey.Name,
                },
                LogicalGroup = (string)variable.GetTag(XenkoTags.LogicalGroup),
                Type = parameterKey.Type,
                RawName = variable.Name,
            };
            
            members.Add(binding);
        }
        private void ValidateConstantBufferReflection(ConstantBuffer constantBufferRaw, ref ConstantBufferDescription constantBufferRawDesc, EffectConstantBufferDescription 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.RawName != variableDescription.Name)
                {
                    log.Error("Variable [{0}] in constant buffer [{1}] has no link", variableDescription.Name, constantBuffer.Name);
                }
                else
                {
                    var parameter = new EffectValueDescription()
                    {
                        Type =
                        {
                            Class = (EffectParameterClass)variableTypeDescription.Class,
                            Type = ConvertVariableValueType(variableTypeDescription.Type, log),
                            Elements = variableTypeDescription.ElementCount,
                            RowCount = (byte)variableTypeDescription.RowCount,
                            ColumnCount = (byte)variableTypeDescription.ColumnCount,
                        },
                        RawName = variableDescription.Name,
                        Offset = variableDescription.StartOffset,
                        Size = variableDescription.Size,
                    };

                    if (parameter.Offset != binding.Offset
                        || parameter.Size != binding.Size
                        || parameter.Type.Elements != binding.Type.Elements
                        || ((parameter.Type.Class != EffectParameterClass.Struct) && // Ignore columns/rows if it's a struct (sometimes it contains weird data)
                               (parameter.Type.RowCount != binding.Type.RowCount || parameter.Type.ColumnCount != binding.Type.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}");
            }
        }
示例#10
0
        private void UpdateConstantBufferReflection(EffectConstantBufferDescription reflectionConstantBuffer)
        {
            // Used to compute constant buffer size and member offsets (std140 rule)
            int constantBufferOffset = 0;

            // Fill members
            for (int index = 0; index < reflectionConstantBuffer.Members.Length; index++)
            {
                var member = reflectionConstantBuffer.Members[index];

                // Properly compute size and offset according to DX rules
                var memberSize = ComputeMemberSize(ref member.Type, ref constantBufferOffset);

                // Store size/offset info
                member.Offset = constantBufferOffset;
                member.Size = memberSize;

                // Adjust offset for next item
                constantBufferOffset += memberSize;

                reflectionConstantBuffer.Members[index] = member;
            }

            // Round buffer size to next multiple of 16
            reflectionConstantBuffer.Size = (constantBufferOffset + 15) / 16 * 16;
        }