/// <summary>
        /// Gets the data related to the shader metadata for a given shader type.
        /// </summary>
        /// <param name="root32BitConstantCount">The total number of needed 32 bit constants in the shader root signature.</param>
        /// <param name="isImplicitTextureUsed">Indicates whether the current shader uses an implicit texture.</param>
        /// <param name="isSamplerUsed">Whether the static sampler is used by the shader.</param>
        /// <param name="capturedFields">The sequence of captured fields for the shader.</param>
        /// <returns>The metadata info for the shader.</returns>
        public static DispatchMetadataInfo GetInfo(
            int root32BitConstantCount,
            bool isImplicitTextureUsed,
            bool isSamplerUsed,
            ImmutableArray <FieldInfo> capturedFields)
        {
            ImmutableArray <ResourceDescriptor> .Builder descriptors = ImmutableArray.CreateBuilder <ResourceDescriptor>();
            int constantBufferOffset    = 1;
            int readOnlyResourceOffset  = 0;
            int readWriteResourceOffset = 0;
            int resourceOffset          = 0;

            // Add the implicit texture descriptor, if needed
            if (isImplicitTextureUsed)
            {
                descriptors.Add(new ResourceDescriptor(1, readWriteResourceOffset++, resourceOffset++));
            }

            // Populate the sequence of resource descriptors
            foreach (FieldInfo.Resource resource in capturedFields.OfType <FieldInfo.Resource>())
            {
                if (HlslKnownTypes.IsConstantBufferType(resource.TypeName))
                {
                    descriptors.Add(new ResourceDescriptor(2, constantBufferOffset++, resourceOffset++));
                }
                else if (HlslKnownTypes.IsReadOnlyTypedResourceType(resource.TypeName))
                {
                    descriptors.Add(new ResourceDescriptor(0, readOnlyResourceOffset++, resourceOffset++));
                }
                else
                {
                    descriptors.Add(new ResourceDescriptor(1, readWriteResourceOffset++, resourceOffset++));
                }
            }

            return(new(
                       root32BitConstantCount,
                       isSamplerUsed,
                       descriptors.ToImmutable()));
        }
        /// <summary>
        /// Loads a specified <see cref="ReadableMember"/> and adds it to the shader model
        /// </summary>
        /// <param name="memberInfo">The target <see cref="ReadableMember"/> to load</param>
        /// <param name="name">The optional explicit name to use for the field</param>
        /// <param name="parents">The list of parent fields to reach the current <see cref="ReadableMember"/> from a given <see cref="Action{T}"/></param>
        private void LoadFieldInfo(ReadableMember memberInfo, string?name = null, IReadOnlyList <ReadableMember>?parents = null)
        {
            Type   fieldType = memberInfo.MemberType;
            string fieldName = HlslKnownKeywords.GetMappedName(name ?? memberInfo.Name);

            // Constant buffer
            if (HlslKnownTypes.IsConstantBufferType(fieldType))
            {
                DescriptorRanges.Add(new DescriptorRange1(DescriptorRangeType.ConstantBufferView, 1, _ConstantBuffersCount));

                // Track the buffer field
                memberInfo.Parents = parents;
                _CapturedMembers.Add(memberInfo);

                string typeName = HlslKnownTypes.GetMappedName(fieldType.GenericTypeArguments[0]);
                _BuffersList.Add(new ConstantBufferFieldInfo(fieldType, typeName, fieldName, _ConstantBuffersCount++));
            }
            else if (HlslKnownTypes.IsReadOnlyBufferType(fieldType))
            {
                // Root parameter for a readonly buffer
                DescriptorRanges.Add(new DescriptorRange1(DescriptorRangeType.ShaderResourceView, 1, _ReadOnlyBuffersCount));

                // Track the buffer field
                memberInfo.Parents = parents;
                _CapturedMembers.Add(memberInfo);

                string typeName = HlslKnownTypes.GetMappedName(fieldType);
                _BuffersList.Add(new ReadOnlyBufferFieldInfo(fieldType, typeName, fieldName, _ReadOnlyBuffersCount++));
            }
            else if (HlslKnownTypes.IsReadWriteBufferType(fieldType))
            {
                // Root parameter for a read write buffer
                DescriptorRanges.Add(new DescriptorRange1(DescriptorRangeType.UnorderedAccessView, 1, _ReadWriteBuffersCount));

                // Track the buffer field
                memberInfo.Parents = parents;
                _CapturedMembers.Add(memberInfo);

                string typeName = HlslKnownTypes.GetMappedName(fieldType);
                _BuffersList.Add(new ReadWriteBufferFieldInfo(fieldType, typeName, fieldName, _ReadWriteBuffersCount++));
            }
            else if (HlslKnownTypes.IsKnownScalarType(fieldType) || HlslKnownTypes.IsKnownVectorType(fieldType))
            {
                // Register the captured field
                memberInfo.Parents = parents;
                _CapturedMembers.Add(memberInfo);

                string typeName = HlslKnownTypes.GetMappedName(fieldType);
                _FieldsList.Add(new CapturedFieldInfo(fieldType, typeName, fieldName));
            }
            else if (fieldType.IsClass && fieldName.StartsWith("CS$<>"))
            {
                // Captured scope, update the parents list
                List <ReadableMember> updatedParents = parents?.ToList() ?? new List <ReadableMember>();
                updatedParents.Add(memberInfo);

                // Recurse on the new compiler generated class
                IReadOnlyList <FieldInfo> fields = fieldType.GetFields().ToArray();
                foreach (FieldInfo fieldInfo in fields)
                {
                    LoadFieldInfo(fieldInfo, null, updatedParents);
                }
            }
            else if (fieldType.IsDelegate() &&
                     memberInfo.GetValue(Action.Target) is Delegate func &&
                     (func.Method.IsStatic || func.Method.DeclaringType.IsStatelessDelegateContainer()) &&
                     (HlslKnownTypes.IsKnownScalarType(func.Method.ReturnType) || HlslKnownTypes.IsKnownVectorType(func.Method.ReturnType)) &&
                     fieldType.GenericTypeArguments.All(type => HlslKnownTypes.IsKnownScalarType(type) ||
                                                        HlslKnownTypes.IsKnownVectorType(type)))
            {
                // Captured static delegates with a return type
                LoadStaticMethodSource(fieldName, func.Method);
            }
        }