Beispiel #1
0
        /// <summary>
        /// Optimizes the slot links.
        /// </summary>
        /// <param name="stageBlock">The stage block.</param>
        private void PrepareSlotLinks(ref StageBlock stageBlock)
        {
            // Allocate slots only when needed
            stageBlock.Slots = new List<SlotLinkSet>[1 + (int)EffectResourceType.UnorderedAccessView];

            // Retrieve Constant buffer resource index as It has been updated by the reordering of resources
            for (int i = 0; i < stageBlock.ConstantBufferLinks.Length; i++)
            {
                stageBlock.ConstantBufferLinks[i].ResourceIndex = stageBlock.ConstantBufferLinks[i].Parameter.Offset;
            }

            // Compute default slot links link
            foreach (var parameter in stageBlock.Parameters)
            {

                var slots = stageBlock.Slots[(int)parameter.ResourceType];
                if (slots == null)
                {
                    slots = new List<SlotLinkSet>();
                    stageBlock.Slots[(int)parameter.ResourceType] = slots;
                }

                var parameterRaw = (EffectData.ResourceParameter)parameter.ParameterDescription;

                var range = new SlotLinkSet() { SlotCount = parameterRaw.Count, SlotIndex = parameterRaw.Slot };
                slots.Add(range);
                range.Links.Add(new SlotLink(parameter.Offset, 0, parameterRaw.Count));
            }

            if (EnableDebug)
            {
                DebugLog.WriteLine("*** Before OptimizeSlotLinks ****");
                PrintLinks(ref stageBlock);
            }

            // Optimize all slots
            foreach (var slotRangePerResourceType in stageBlock.Slots)
            {
                if (slotRangePerResourceType == null)
                    continue;

                var previousRange = slotRangePerResourceType[0];

                for (int i = 1; i < slotRangePerResourceType.Count; i++)
                {
                    var currentRange = slotRangePerResourceType[i];
                    int endIndex = previousRange.SlotIndex + previousRange.SlotCount;

                    var delta = (currentRange.SlotIndex - endIndex);

                    // If there is at maximum a 1 
                    if (delta <= 1)
                    {
                        foreach (var slotLink in currentRange.Links)
                        {
                            var previousLink = previousRange.Links[previousRange.Links.Count - 1];
                            // Merge consecutive individual slot link
                            if ((previousLink.GlobalIndex + previousLink.SlotCount) == slotLink.GlobalIndex && (previousLink.SlotIndex + previousLink.SlotCount) == (currentRange.SlotIndex + slotLink.SlotIndex))
                            {
                                previousLink.SlotCount += slotLink.SlotCount;
                                previousRange.Links[previousRange.Links.Count - 1] = previousLink;
                            }
                            else
                            {
                                previousRange.Links.Add(new SlotLink(slotLink.GlobalIndex, (slotLink.SlotIndex + previousRange.SlotCount + delta), slotLink.SlotCount));
                            }
                        }

                        // Update the total slot count
                        previousRange.SlotCount += delta + currentRange.SlotCount;

                        slotRangePerResourceType.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        previousRange = currentRange;
                    }
                }
            }

            if (EnableDebug)
            {
                DebugLog.WriteLine("*** After OptimizeSlotLinks ****");
                PrintLinks(ref stageBlock);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Initializes the stage block.
        /// </summary>
        /// <param name="stageBlock">The stage block.</param>
        /// <param name="logger">The logger.</param>
        private void InitStageBlock(StageBlock stageBlock, Logger logger)
        {
            // If null shader, then skip init
            if (stageBlock.Index < 0)
            {
                return;
            }

            stageBlock.Shader = Effect.Pool.GetOrCompileShader(stageBlock.Type, stageBlock.Index);
            var shaderRaw = Effect.Pool.EffectData.Shaders[stageBlock.Index];

            // Cache the input signature
            if (shaderRaw.Type == EffectShaderType.Vertex)
            {
                inputSignatureManager = graphicsDevice.GetOrCreateInputSignatureManager(shaderRaw.InputSignature.Bytecode, shaderRaw.InputSignature.Hashcode);
            }

            for (int i = 0; i < shaderRaw.ConstantBuffers.Count; i++)
            {
                var constantBufferRaw = shaderRaw.ConstantBuffers[i];

                // Constant buffers with a null size are skipped
                if (constantBufferRaw.Size == 0)
                    continue;

                var constantBuffer = Effect.GetOrCreateConstantBuffer(Effect.GraphicsDevice, constantBufferRaw);
                // IF constant buffer is null, it means that there is a conflict
                if (constantBuffer == null)
                {
                    logger.Error("Constant buffer [{0}] cannot have multiple size or different content declaration inside the same effect pool", constantBufferRaw.Name);
                    continue;
                }
                
                // Test if this constant buffer is not already part of the effect
                if (Effect.ConstantBuffers[constantBufferRaw.Name] == null)
                {
                    // Add the declared constant buffer to the effect shader.
                    Effect.ConstantBuffers.Add(constantBuffer);

                    // Declare all parameter from constant buffer at the effect level.
                    foreach (var parameter in constantBuffer.Parameters)
                    {
                        var previousParameter = Effect.Parameters[parameter.Name];
                        if (previousParameter == null)
                        {
                            // Add an effect parameter linked to the approriate constant buffer at the effect level.
                            Effect.Parameters.Add(new EffectParameter((EffectData.ValueTypeParameter) parameter.ParameterDescription, constantBuffer));
                        }
                        else if (parameter.ParameterDescription != previousParameter.ParameterDescription || parameter.buffer != previousParameter.buffer)
                        {
                            // If registered parameters is different
                            logger.Error("Parameter [{0}] defined in Constant buffer [{0}] is already defined by another constant buffer with the definition [{2}]", parameter, constantBuffer.Name, previousParameter);
                        }
                    }
                }
            }

            var constantBufferLinks = new List<ConstantBufferLink>();

            // Declare all resource parameters at the effect level.
            foreach (var parameterRaw in shaderRaw.ResourceParameters)
            {
                EffectParameter parameter;
                var previousParameter = Effect.Parameters[parameterRaw.Name];

                // Skip enmpty constant buffers.
                if (parameterRaw.Type == EffectParameterType.ConstantBuffer && Effect.ConstantBuffers[parameterRaw.Name] == null)
                {
                    continue;
                }

                int resourceIndex = Effect.ResourceLinker.Count;

                if (previousParameter == null)
                {
                    parameter = new EffectParameter(parameterRaw, EffectResourceTypeHelper.ConvertFromParameterType(parameterRaw.Type), Effect.ResourceLinker.Count, Effect.ResourceLinker);
                    Effect.Parameters.Add(parameter);

                    Effect.ResourceLinker.Count++;
                }
                else
                {
                    resourceIndex = ((EffectData.ResourceParameter) previousParameter.ParameterDescription).Slot;

                    if (CompareResourceParameter(parameterRaw, (EffectData.ResourceParameter) previousParameter.ParameterDescription))
                    {
                        // If registered parameters is different
                        logger.Error("Resource Parameter [{0}] is already defined with a different definition [{1}]", parameterRaw, previousParameter.ParameterDescription);
                    }
                    parameter = previousParameter;
                }

                // For constant buffers, we need to store explicit link
                if (parameter.ResourceType == EffectResourceType.ConstantBuffer)
                {
                    constantBufferLinks.Add(new ConstantBufferLink(Effect.ConstantBuffers[parameter.Name], parameter.Offset));
                }

                // Allocate slots only when needed
                if (stageBlock.Slots == null)
                {
                    stageBlock.Slots = new List<SlotLinkSet>[1 + (int) EffectResourceType.SamplerState];
                }

                var slots = stageBlock.Slots[(int) parameter.ResourceType];
                if (slots == null)
                {
                    slots = new List<SlotLinkSet>();
                    stageBlock.Slots[(int) parameter.ResourceType] = slots;
                }

                var range = new SlotLinkSet() {SlotCount = parameterRaw.Count, SlotIndex = parameterRaw.Slot};
                slots.Add(range);
                range.Links.Add(new SlotLink(parameter.Offset, 0, parameterRaw.Count));
            }

            stageBlock.ConstantBufferLinks = constantBufferLinks.ToArray();

            // Optimize the current stage block
            OptimizeSlotLinks(ref stageBlock);
        }