Exemple #1
0
        private void UpdateConstantBufferReflection(ShaderConstantBufferDescription 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, ref constantBufferOffset);

                // Align offset and store it as member offset
                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;
        }
Exemple #2
0
        public ResourceGroupDescription(DescriptorSetLayoutBuilder descriptorSetLayout, ShaderConstantBufferDescription 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);
            }
        }
        public ParameterConstantBuffer(GraphicsDevice device, string constantBufferName, ShaderConstantBufferDescription constantBufferDesc)
        {
            ConstantBufferDesc  = constantBufferDesc;
            constantBufferDatas = new ConstantBufferData[GraphicsDevice.ThreadCount];
            dataStreams         = new DataPointer[GraphicsDevice.ThreadCount];

            for (uint i = 0; i < GraphicsDevice.ThreadCount; ++i)
            {
                constantBufferDatas[i] = new ConstantBufferData(constantBufferDesc);
                dataStreams[i]         = new DataPointer(constantBufferDatas[i].Data, constantBufferDesc.Size);
            }

            Buffer = SiliconStudio.Xenko.Graphics.Buffer.New(device, constantBufferDatas[0].Desc.Size, BufferFlags.ConstantBuffer, UsingMap ? GraphicsResourceUsage.Dynamic : GraphicsResourceUsage.Default);

            // We want to clear flags
            // TODO: Should be later replaced with either an internal field on GraphicsResourceBase, or a reset counter somewhere?
            Buffer.Reload = Reload;
        }
Exemple #4
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 #5
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);

                ShaderConstantBufferDescription 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);
            }
        }
        /// <summary>
        /// Create or updates the reflection for this shader
        /// </summary>
        /// <param name="effectReflection">the reflection from the hlsl</param>
        /// <param name="stage">the shader pipeline stage</param>
        private void CreateReflection(EffectReflection effectReflection, ShaderStage stage)
        {
            int currentProgram;

            GL.GetInteger(GetPName.CurrentProgram, out currentProgram);
            GL.UseProgram(resourceId);

            int uniformBlockCount;

            GL.GetProgram(resourceId, PdxActiveUniformBlocks, out uniformBlockCount);

            for (int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
            {
                // TODO: get previous name to find te actual constant buffer in the reflexion
#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                const int sbCapacity = 128;
                int       length;
                var       sb = new StringBuilder(sbCapacity);
                GL.GetActiveUniformBlockName(resourceId, uniformBlockIndex, sbCapacity, out length, sb);
                var constantBufferName = sb.ToString();
#else
                var constantBufferName = GL.GetActiveUniformBlockName(resourceId, uniformBlockIndex);
#endif

                var constantBufferDescriptionIndex = effectReflection.ConstantBuffers.FindIndex(x => x.Name == constantBufferName);
                if (constantBufferDescriptionIndex == -1)
                {
                    reflectionResult.Error("Unable to find the constant buffer description [{0}]", constantBufferName);
                    return;
                }
                var constantBufferIndex = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == constantBufferName);
                if (constantBufferIndex == -1)
                {
                    reflectionResult.Error("Unable to find the constant buffer [{0}]", constantBufferName);
                    return;
                }

                var constantBufferDescription = effectReflection.ConstantBuffers[constantBufferDescriptionIndex];
                var constantBuffer            = effectReflection.ResourceBindings[constantBufferIndex];

                GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockDataSize, out constantBufferDescription.Size);

                int uniformCount;
                GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockActiveUniforms, out uniformCount);

                // set the binding
                GL.UniformBlockBinding(resourceId, uniformBlockIndex, uniformBlockIndex);

                // Read uniforms desc
                var uniformIndices = new int[uniformCount];
                var uniformOffsets = new int[uniformCount];
                var uniformTypes   = new int[uniformCount];
                var uniformNames   = new string[uniformCount];
                GL.GetActiveUniformBlock(resourceId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockActiveUniformIndices, uniformIndices);
                GL.GetActiveUniforms(resourceId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformOffset, uniformOffsets);
                GL.GetActiveUniforms(resourceId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformType, uniformTypes);

                for (int uniformIndex = 0; uniformIndex < uniformIndices.Length; ++uniformIndex)
                {
#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    int size;
                    ActiveUniformType aut;
                    GL.GetActiveUniform(resourceId, uniformIndices[uniformIndex], sbCapacity, out length, out size, out aut, sb);
                    uniformNames[uniformIndex] = sb.ToString();
#else
                    uniformNames[uniformIndex] = GL.GetActiveUniformName(resourceId, uniformIndices[uniformIndex]);
#endif
                }

                // Reoder by offset
                var indexMapping = uniformIndices.Select((x, i) => new UniformMergeInfo {
                    Offset = uniformOffsets[i], Type = (ActiveUniformType)uniformTypes[i], Name = uniformNames[i], NextOffset = 0
                }).OrderBy(x => x.Offset).ToArray();
                indexMapping.Last().NextOffset = constantBufferDescription.Size;

                // Fill next offsets
                for (int i = 1; i < indexMapping.Length; ++i)
                {
                    indexMapping[i - 1].NextOffset = indexMapping[i].Offset;
                }

                // Group arrays/structures into one variable (std140 layout is enough for offset determinism inside arrays/structures)
                indexMapping = indexMapping.GroupBy(x =>
                {
                    // Use only first part of name (ignore structure/array part)
                    var name = x.Name;
                    if (name.Contains("."))
                    {
                        name = name.Substring(0, name.IndexOf('.'));
                    }
                    if (name.Contains("["))
                    {
                        name = name.Substring(0, name.IndexOf('['));
                    }
                    return(name);
                })
                               .Select(x =>
                {
                    var result        = x.First();
                    result.NextOffset = x.Last().NextOffset;

                    // Check weither it's an array or a struct
                    int dotIndex   = result.Name.IndexOf('.');
                    int arrayIndex = result.Name.IndexOf('[');

                    if (x.Count() > 1 && arrayIndex == -1 && dotIndex == -1)
                    {
                        throw new InvalidOperationException();
                    }

                    // TODO: Type processing

                    result.Name = x.Key;
                    return(result);
                }).ToArray();

                foreach (var variableIndexGroup in indexMapping)
                {
                    var variableIndex = -1;
                    for (var tentativeIndex = 0; tentativeIndex < constantBufferDescription.Members.Length; ++tentativeIndex)
                    {
                        if (constantBufferDescription.Members[tentativeIndex].Param.RawName == variableIndexGroup.Name)
                        {
                            variableIndex = tentativeIndex;
                            break;
                        }
                    }

                    if (variableIndex == -1)
                    {
                        reflectionResult.Error("Unable to find uniform [{0}] in constant buffer [{1}]", variableIndexGroup.Name, constantBufferName);
                        continue;
                    }
                    var variable = constantBufferDescription.Members[variableIndex];
                    variable.Param.Type = GetTypeFromActiveUniformType(variableIndexGroup.Type);
                    variable.Offset     = variableIndexGroup.Offset;
                    variable.Size       = variableIndexGroup.NextOffset - variableIndexGroup.Offset;

                    constantBufferDescription.Members[variableIndex] = variable;
                }

                constantBufferDescription.Stage = stage;
                constantBufferDescription.Type  = ConstantBufferType.ConstantBuffer;

                constantBuffer.SlotCount = 1; // constant buffers are not arrays
                constantBuffer.SlotStart = uniformBlockIndex;
                constantBuffer.Stage     = stage;

                // store the new values
                effectReflection.ConstantBuffers[constantBufferDescriptionIndex] = constantBufferDescription;
                effectReflection.ResourceBindings[constantBufferIndex]           = constantBuffer;
            }
//#endif

            // Register textures, samplers, etc...
            //TODO: (?) non texture/buffer uniform outside of a block
            {
                // Register "NoSampler", required by HLSL=>GLSL translation to support HLSL such as texture.Load().
                var noSampler = new EffectParameterResourceData {
                    Param = { RawName = "NoSampler", KeyName = "NoSampler", Class = EffectParameterClass.Sampler }, SlotStart = -1
                };
                effectBytecode.Reflection.ResourceBindings.Add(noSampler);
                bool usingSamplerNoSampler = false;

                int activeUniformCount;
                GL.GetProgram(resourceId, ProgramParameter.ActiveUniforms, out activeUniformCount);
#if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                var uniformTypes = new int[activeUniformCount];
                GL.GetActiveUniforms(resourceId, activeUniformCount, Enumerable.Range(0, activeUniformCount).ToArray(), ActiveUniformParameter.UniformType, uniformTypes);
#endif

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                if (GraphicsDevice.IsOpenGLES2)
                {
                    // Register global "fake" cbuffer
                    //var constantBuffer = new ShaderReflectionConstantBuffer
                    //    {
                    //        Name = "$Globals",
                    //        Variables = new List<ShaderReflectionVariable>(),
                    //        Type = ConstantBufferType.ConstantBuffer
                    //    };
                    //shaderReflection.ConstantBuffers.Add(constantBuffer);
                    //shaderReflection.BoundResources.Add(new InputBindingDescription { BindPoint = 0, BindCount = 1, Name = constantBuffer.Name, Type = ShaderInputType.ConstantBuffer });

                    // reset the size of the constant buffers
                    foreach (var constantBuffer in effectReflection.ConstantBuffers)
                    {
                        constantBuffer.Size = 0;
                    }

                    // set the state of the constant buffers
                    foreach (var constantBuffer in effectReflection.ConstantBuffers)
                    {
                        constantBuffer.Stage = stage;
                    }
                    for (int i = 0; i < effectReflection.ResourceBindings.Count; i++)
                    {
                        if (effectReflection.ResourceBindings[i].Param.Class != EffectParameterClass.ConstantBuffer)
                        {
                            continue;
                        }

                        var globalConstantBufferCopy = effectReflection.ResourceBindings[i];
                        globalConstantBufferCopy.Stage       = stage;
                        effectReflection.ResourceBindings[i] = globalConstantBufferCopy;
                    }

                    //Create a Globals constant buffer if necessary
                    var globalConstantBufferDescriptionIndex = effectReflection.ConstantBuffers.FindIndex(x => x.Name == "Globals");
                    var globalConstantBufferIndex            = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == "Globals");
                    if (globalConstantBufferDescriptionIndex == -1 && globalConstantBufferIndex == -1)
                    {
                        var newConstantBufferDescription = new ShaderConstantBufferDescription
                        {
                            Name    = "Globals",
                            Stage   = stage,
                            Type    = ConstantBufferType.ConstantBuffer,
                            Size    = 0,
                            Members = new EffectParameterValueData[0],
                        };
                        var newConstantBuffer = new EffectParameterResourceData
                        {
                            Stage     = stage,
                            SlotStart = 0,
                            SlotCount = 1,
                            Param     = { RawName = "Globals", KeyName = "Globals", Type = EffectParameterType.ConstantBuffer, Class = EffectParameterClass.ConstantBuffer }
                        };

                        effectReflection.ConstantBuffers.Add(newConstantBufferDescription);
                        effectReflection.ResourceBindings.Add(newConstantBuffer);

                        globalConstantBufferDescriptionIndex = effectReflection.ConstantBuffers.Count - 1;
                        globalConstantBufferIndex            = effectReflection.ResourceBindings.Count - 1;
                    }

                    // Merge all the variables in the Globals constant buffer
                    if (globalConstantBufferDescriptionIndex != -1 && globalConstantBufferIndex != -1)
                    {
                        var globalConstantBufferDescription = effectReflection.ConstantBuffers[globalConstantBufferDescriptionIndex];
                        for (int cstDescrIndex = 0; cstDescrIndex < effectReflection.ConstantBuffers.Count; ++cstDescrIndex)
                        {
                            if (cstDescrIndex == globalConstantBufferDescriptionIndex)
                            {
                                continue;
                            }

                            var currentConstantBufferDescription = effectReflection.ConstantBuffers[cstDescrIndex];

                            globalConstantBufferDescription.Members = ArrayExtensions.Concat(
                                globalConstantBufferDescription.Members, currentConstantBufferDescription.Members);

                            effectReflection.ResourceBindings.RemoveAll(x => x.Param.RawName == currentConstantBufferDescription.Name);
                        }

                        // only keep the active uniforms
                        globalConstantBufferDescription.Members =
                            globalConstantBufferDescription.Members.Where(x => GL.GetUniformLocation(resourceId,
#if SILICONSTUDIO_PLATFORM_ANDROID
                                                                                                     new StringBuilder(x.Param.RawName)
#else
                                                                                                     x.Param.RawName
#endif
                                                                                                     ) >= 0).ToArray();

                        // remove all the constant buffers and their resource bindings except the Globals one
                        effectReflection.ConstantBuffers.Clear();
                        effectReflection.ConstantBuffers.Add(globalConstantBufferDescription);
                    }
                    else if (globalConstantBufferDescriptionIndex != -1 && globalConstantBufferIndex == -1)
                    {
                        reflectionResult.Error("Globals constant buffer has a description and no resource binding");
                    }
                    else if (globalConstantBufferDescriptionIndex == -1 && globalConstantBufferIndex != -1)
                    {
                        reflectionResult.Error("Globals constant buffer has a description and no resource binding");
                    }
                }
#endif

                int textureUnitCount = 0;

                const int sbCapacity = 128;
                int       length;
                var       sb = new StringBuilder(sbCapacity);

                for (int activeUniformIndex = 0; activeUniformIndex < activeUniformCount; ++activeUniformIndex)
                {
#if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    var uniformType = (ActiveUniformType)uniformTypes[activeUniformIndex];
                    var uniformName = GL.GetActiveUniformName(resourceId, activeUniformIndex);
#else
                    ActiveUniformType uniformType;
                    int uniformCount;
                    GL.GetActiveUniform(resourceId, activeUniformIndex, sbCapacity, out length, out uniformCount, out uniformType, sb);
                    var uniformName = sb.ToString();
                    //int uniformSize;
                    //GL.GetActiveUniform(resourceId, activeUniformIndex, out uniformSize, ActiveUniformType.Float);
#endif

                    switch (uniformType)
                    {
#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    case ActiveUniformType.Bool:
                    case ActiveUniformType.Int:
                        AddUniform(effectReflection, sizeof(int) * 1, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.BoolVec2:
                    case ActiveUniformType.IntVec2:
                        AddUniform(effectReflection, sizeof(int) * 2, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.BoolVec3:
                    case ActiveUniformType.IntVec3:
                        AddUniform(effectReflection, sizeof(int) * 3, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.BoolVec4:
                    case ActiveUniformType.IntVec4:
                        AddUniform(effectReflection, sizeof(int) * 4, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.Float:
                        AddUniform(effectReflection, sizeof(float) * 1, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.FloatVec2:
                        AddUniform(effectReflection, sizeof(float) * 2, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.FloatVec3:
                        AddUniform(effectReflection, sizeof(float) * 3, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.FloatVec4:
                        AddUniform(effectReflection, sizeof(float) * 4, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.FloatMat4:
                        AddUniform(effectReflection, sizeof(float) * 4 * 4, uniformCount, uniformName, uniformType);
                        break;

                    case ActiveUniformType.FloatMat2:
                    case ActiveUniformType.FloatMat3:
                        throw new NotImplementedException();
#endif
#if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    case ActiveUniformType.Sampler1D:
                    case ActiveUniformType.Sampler1DShadow:
#endif
                    case ActiveUniformType.Sampler2D:
                    case ActiveUniformType.Sampler3D:     // TODO: remove Texture3D that is not available in OpenGL ES 2
                    case ActiveUniformType.SamplerCube:
                    case ActiveUniformType.Sampler2DShadow:
#if SILICONSTUDIO_PLATFORM_ANDROID
                        var uniformIndex = GL.GetUniformLocation(resourceId, new StringBuilder(uniformName));
#else
                        var uniformIndex = GL.GetUniformLocation(resourceId, uniformName);
#endif

                        // Temporary way to scan which texture and sampler created this texture_sampler variable (to fix with new HLSL2GLSL converter)

                        var startIndex             = -1;
                        var textureReflectionIndex = -1;
                        var samplerReflectionIndex = -1;
                        do
                        {
                            int middlePart  = uniformName.IndexOf('_', startIndex + 1);
                            var textureName = middlePart != -1 ? uniformName.Substring(0, middlePart) : uniformName;
                            var samplerName = middlePart != -1 ? uniformName.Substring(middlePart + 1) : null;

                            textureReflectionIndex =
                                effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == textureName);
                            samplerReflectionIndex =
                                effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == samplerName);

                            if (textureReflectionIndex != -1 && samplerReflectionIndex != -1)
                            {
                                break;
                            }

                            startIndex = middlePart;
                        } while (startIndex != -1);

                        if (startIndex == -1 || textureReflectionIndex == -1 || samplerReflectionIndex == -1)
                        {
                            reflectionResult.Error("Unable to find sampler and texture corresponding to [{0}]", uniformName);
                            continue;     // Error
                        }

                        var textureReflection = effectReflection.ResourceBindings[textureReflectionIndex];
                        var samplerReflection = effectReflection.ResourceBindings[samplerReflectionIndex];

                        // Contrary to Direct3D, samplers and textures are part of the same object in OpenGL
                        // Since we are exposing the Direct3D representation, a single sampler parameter key can be used for several textures, a single texture can be used with several samplers.
                        // When such a case is detected, we need to duplicate the resource binding.
                        textureReflectionIndex = GetReflexionIndex(textureReflection, textureReflectionIndex, effectReflection.ResourceBindings);
                        samplerReflectionIndex = GetReflexionIndex(samplerReflection, samplerReflectionIndex, effectReflection.ResourceBindings);

                        // Update texture uniform mapping
                        GL.Uniform1(uniformIndex, textureUnitCount);

                        textureReflection.Stage = stage;
                        //textureReflection.Param.RawName = uniformName;
                        textureReflection.Param.Type  = GetTypeFromActiveUniformType(uniformType);
                        textureReflection.SlotStart   = textureUnitCount;
                        textureReflection.SlotCount   = 1;   // TODO: texture arrays
                        textureReflection.Param.Class = EffectParameterClass.ShaderResourceView;

                        samplerReflection.Stage       = stage;
                        samplerReflection.SlotStart   = textureUnitCount;
                        samplerReflection.SlotCount   = 1;   // TODO: texture arrays
                        samplerReflection.Param.Class = EffectParameterClass.Sampler;

                        effectReflection.ResourceBindings[textureReflectionIndex] = textureReflection;
                        effectReflection.ResourceBindings[samplerReflectionIndex] = samplerReflection;

                        Textures.Add(new Texture(textureUnitCount));

                        textureUnitCount++;
                        break;
                    }
                }

                // Remove any optimized resource binding
                effectReflection.ResourceBindings.RemoveAll(x => x.SlotStart == -1);
            }

            GL.UseProgram(currentProgram);
        }
Exemple #7
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 #8
0
 public ConstantBufferData(ShaderConstantBufferDescription description)
 {
     Desc = description;
     Data = Marshal.AllocHGlobal(Desc.Size);
     constantBufferParams = new BoundConstantBufferParam[Desc.Members.Length];
 }
Exemple #9
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 #10
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 #11
0
 public ConstantBufferData(ShaderConstantBufferDescription description)
 {
     Desc = description;
     Data = Marshal.AllocHGlobal(Desc.Size);
     constantBufferParams = new ParameterCollectionGroup.BoundInternalValue[Desc.Members.Length];
 }
Exemple #12
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
            // clean the name
            if (uniformName.Contains("."))
            {
                uniformName = uniformName.Substring(0, uniformName.IndexOf('.'));
            }
            if (uniformName.Contains("["))
            {
                uniformName = uniformName.Substring(0, uniformName.IndexOf('['));
            }

            // check that this uniform is in a constant buffer
            int indexOfConstantBuffer = -1;
            int indexOfMember         = -1;
            ShaderConstantBufferDescription 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.Param.RawName.Equals(uniformName))
                    {
                        indexOfConstantBuffer     = cbIndex;
                        indexOfMember             = index;
                        constantBufferDescription = currentConstantBuffer;
                        break;
                    }
                }
                if (constantBufferDescription != null)
                {
                    break;
                }
            }

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

            if (GraphicsDevice.IsOpenGLES2)
            {
                var indexOfResource = effectReflection.ResourceBindings.FindIndex(x => x.Param.RawName == constantBufferDescription.Name);
                if (indexOfResource == -1)
                {
                    reflectionResult.Error("Unable to find uniform [{0}] in any constant buffer", uniformName);
                    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;

                // Check type
                var variable = constantBufferDescription.Members[indexOfMember];
                if (variable.Param.Type != GetTypeFromActiveUniformType(uniformType))
                {
                    throw new InvalidOperationException($"Uniform [{uniformName}] type [{variable.Param.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        = variable.Size,
                    ConstantBufferSlot = constantBuffer.SlotStart,
                    Offset             = variable.Offset,
                    UniformIndex       = GL.GetUniformLocation(resourceId, uniformName)
                });
            }
        }
Exemple #13
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}");
            }
        }
Exemple #14
0
 public static void ProcessConstantBuffer(this ParameterCollectionLayout parameterCollectionLayout, ShaderConstantBufferDescription constantBuffer)
 {
     foreach (var member in constantBuffer.Members)
     {
         parameterCollectionLayout.LayoutParameterKeyInfos.Add(new ParameterKeyInfo(member.Param.Key, parameterCollectionLayout.BufferSize + member.Offset, member.Count > 0 ? member.Count : 1));
     }
     parameterCollectionLayout.BufferSize += constantBuffer.Size;
 }