Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        private static void LinkVariable(EffectReflection reflection, string variableName, LocalParameterKey parameterKey, int slotCount)
        {
            var binding = new EffectResourceBindingDescription {
                KeyInfo = { KeyName = parameterKey.Name }, Class = parameterKey.Type.Class, Type = parameterKey.Type.Type, RawName = variableName, SlotStart = -1, SlotCount = slotCount > 0 ? slotCount : 1, ResourceGroup = parameterKey.ResourceGroup, LogicalGroup = parameterKey.LogicalGroup
            };

            reflection.ResourceBindings.Add(binding);
        }
Exemplo n.º 3
0
        private static void UpdateResourceBindingKey(ref EffectResourceBindingDescription binding)
        {
            var keyName = binding.KeyInfo.KeyName;

            switch (binding.Class)
            {
            case EffectParameterClass.Sampler:
                binding.KeyInfo.Key = FindOrCreateResourceKey <SamplerState>(keyName);
                break;

            case EffectParameterClass.ConstantBuffer:
            case EffectParameterClass.TextureBuffer:
            case EffectParameterClass.ShaderResourceView:
            case EffectParameterClass.UnorderedAccessView:
                switch (binding.Type)
                {
                case EffectParameterType.Buffer:
                case EffectParameterType.ConstantBuffer:
                case EffectParameterType.TextureBuffer:
                case EffectParameterType.AppendStructuredBuffer:
                case EffectParameterType.ByteAddressBuffer:
                case EffectParameterType.ConsumeStructuredBuffer:
                case EffectParameterType.StructuredBuffer:
                case EffectParameterType.RWBuffer:
                case EffectParameterType.RWStructuredBuffer:
                case EffectParameterType.RWByteAddressBuffer:
                    binding.KeyInfo.Key = FindOrCreateResourceKey <Buffer>(keyName);
                    break;

                case EffectParameterType.Texture:
                case EffectParameterType.Texture1D:
                case EffectParameterType.Texture1DArray:
                case EffectParameterType.RWTexture1D:
                case EffectParameterType.RWTexture1DArray:
                case EffectParameterType.Texture2D:
                case EffectParameterType.Texture2DArray:
                case EffectParameterType.Texture2DMultisampled:
                case EffectParameterType.Texture2DMultisampledArray:
                case EffectParameterType.RWTexture2D:
                case EffectParameterType.RWTexture2DArray:
                case EffectParameterType.TextureCube:
                case EffectParameterType.TextureCubeArray:
                case EffectParameterType.RWTexture3D:
                case EffectParameterType.Texture3D:
                    binding.KeyInfo.Key = FindOrCreateResourceKey <Texture>(keyName);
                    break;
                }
                break;
            }

            if (binding.KeyInfo.Key == null)
            {
                throw new InvalidOperationException(string.Format("Unable to find/generate key [{0}] with unsupported type [{1}/{2}]", binding.KeyInfo.KeyName, binding.Class, binding.Type));
            }
        }
 /// <summary>
 /// Inserts the data in the list if this is a copy of a previously set one.
 /// </summary>
 /// <param name="data">The  data.</param>
 /// <param name="index">The index in the list.</param>
 /// <param name="bindings">The list of bindings.</param>
 /// <returns>The new index of the data.</returns>
 private static int GetReflexionIndex(EffectResourceBindingDescription data, int index, FastList <EffectResourceBindingDescription> bindings)
 {
     if (data.SlotCount != 0)
     {
         // slot count has been specified, this means that this resource was already configured
         // We have to create a new entry for the data
         var newIndex = bindings.Count;
         bindings.Add(data);
         return(newIndex);
     }
     return(index);
 }
Exemplo n.º 5
0
        private EffectResourceBindingDescription GetResourceBinding(SharpDX.D3DCompiler.InputBindingDescription bindingDescriptionRaw, string name, LoggerResult log)
        {
            var paramClass = EffectParameterClass.Object;
            var paramType  = EffectParameterType.Void;

            switch (bindingDescriptionRaw.Type)
            {
            case SharpDX.D3DCompiler.ShaderInputType.TextureBuffer:
                paramType  = EffectParameterType.TextureBuffer;
                paramClass = EffectParameterClass.TextureBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.ConstantBuffer:
                paramType  = EffectParameterType.ConstantBuffer;
                paramClass = EffectParameterClass.ConstantBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.Texture:
                paramClass = EffectParameterClass.ShaderResourceView;
                switch (bindingDescriptionRaw.Dimension)
                {
                case SharpDX.Direct3D.ShaderResourceViewDimension.Buffer:
                    paramType = EffectParameterType.Buffer;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1D:
                    paramType = EffectParameterType.Texture1D;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1DArray:
                    paramType = EffectParameterType.Texture1DArray;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D:
                    paramType = EffectParameterType.Texture2D;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DArray:
                    paramType = EffectParameterType.Texture2DArray;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DMultisampled:
                    paramType = EffectParameterType.Texture2DMultisampled;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DMultisampledArray:
                    paramType = EffectParameterType.Texture2DMultisampledArray;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture3D:
                    paramType = EffectParameterType.Texture3D;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.TextureCube:
                    paramType = EffectParameterType.TextureCube;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.TextureCubeArray:
                    paramType = EffectParameterType.TextureCubeArray;
                    break;
                }
                break;

            case SharpDX.D3DCompiler.ShaderInputType.Structured:
                paramClass = EffectParameterClass.ShaderResourceView;
                paramType  = EffectParameterType.StructuredBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.ByteAddress:
                paramClass = EffectParameterClass.ShaderResourceView;
                paramType  = EffectParameterType.ByteAddressBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWTyped:
                paramClass = EffectParameterClass.UnorderedAccessView;
                switch (bindingDescriptionRaw.Dimension)
                {
                case SharpDX.Direct3D.ShaderResourceViewDimension.Buffer:
                    paramType = EffectParameterType.RWBuffer;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1D:
                    paramType = EffectParameterType.RWTexture1D;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1DArray:
                    paramType = EffectParameterType.RWTexture1DArray;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D:
                    paramType = EffectParameterType.RWTexture2D;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DArray:
                    paramType = EffectParameterType.RWTexture2DArray;
                    break;

                case SharpDX.Direct3D.ShaderResourceViewDimension.Texture3D:
                    paramType = EffectParameterType.RWTexture3D;
                    break;
                }
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWStructured:
                paramClass = EffectParameterClass.UnorderedAccessView;
                paramType  = EffectParameterType.RWStructuredBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWByteAddress:
                paramClass = EffectParameterClass.UnorderedAccessView;
                paramType  = EffectParameterType.RWByteAddressBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewAppendStructured:
                paramClass = EffectParameterClass.UnorderedAccessView;
                paramType  = EffectParameterType.AppendStructuredBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewConsumeStructured:
                paramClass = EffectParameterClass.UnorderedAccessView;
                paramType  = EffectParameterType.ConsumeStructuredBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWStructuredWithCounter:
                paramClass = EffectParameterClass.UnorderedAccessView;
                paramType  = EffectParameterType.RWStructuredBuffer;
                break;

            case SharpDX.D3DCompiler.ShaderInputType.Sampler:
                paramClass = EffectParameterClass.Sampler;
                paramType  = EffectParameterType.Sampler;
                break;
            }

            var binding = new EffectResourceBindingDescription()
            {
                KeyInfo =
                {
                    KeyName = name,
                },
                RawName   = bindingDescriptionRaw.Name,
                Class     = paramClass,
                Type      = paramType,
                SlotStart = bindingDescriptionRaw.BindPoint,
                SlotCount = bindingDescriptionRaw.BindCount,
            };

            return(binding);
        }
        /// <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(ProgramId);

            int uniformBlockCount;

            GL.GetProgram(ProgramId, XkActiveUniformBlocks, out uniformBlockCount);

            var validConstantBuffers = new bool[effectReflection.ConstantBuffers.Count];

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

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

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

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

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

                // set the binding
                GL.UniformBlockBinding(ProgramId, 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(ProgramId, uniformBlockIndex, ActiveUniformBlockParameter.UniformBlockActiveUniformIndices, uniformIndices);
                GL.GetActiveUniforms(ProgramId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformOffset, uniformOffsets);
                GL.GetActiveUniforms(ProgramId, uniformIndices.Length, uniformIndices, ActiveUniformParameter.UniformType, uniformTypes);

                for (int uniformIndex = 0; uniformIndex < uniformIndices.Length; ++uniformIndex)
                {
#if STRIDE_GRAPHICS_API_OPENGLES
                    int size;
                    ActiveUniformType aut;
                    GL.GetActiveUniform(ProgramId, uniformIndices[uniformIndex], sbCapacity, out length, out size, out aut, sb);
                    uniformNames[uniformIndex] = sb.ToString();
#else
                    uniformNames[uniformIndex] = GL.GetActiveUniformName(ProgramId, 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].RawName == variableIndexGroup.Name)
                        {
                            variableIndex = tentativeIndex;
                            break;
                        }
                    }

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

                    constantBufferDescription.Members[variableIndex] = variable;
                }

                constantBufferDescription.Type = ConstantBufferType.ConstantBuffer;

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

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

            // Remove unecessary cbuffer and resource bindings

            // 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 EffectResourceBindingDescription {
                    KeyInfo = { KeyName = "NoSampler" }, RawName = "NoSampler", Class = EffectParameterClass.Sampler, SlotStart = -1, SlotCount = 1
                };
                Reflection.ResourceBindings.Add(noSampler);

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

                int textureUnitCount = 0;

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

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

                    //this is a special OpenglES case , it is declared as built in uniform, and the driver will take care of it, we just need to ignore it here
                    if (uniformName.StartsWith("gl_DepthRange"))
                    {
                        continue;
                    }
#endif

                    switch (uniformType)
                    {
#if !STRIDE_GRAPHICS_API_OPENGLES
                    case ActiveUniformType.Sampler1D:
                    case ActiveUniformType.Sampler1DShadow:
                    case ActiveUniformType.IntSampler1D:
                    case ActiveUniformType.UnsignedIntSampler1D:

                    case ActiveUniformType.SamplerBuffer:
                    case ActiveUniformType.UnsignedIntSamplerBuffer:
                    case ActiveUniformType.IntSamplerBuffer:
#endif
                    case ActiveUniformType.Sampler2D:
                    case ActiveUniformType.Sampler2DShadow:
                    case ActiveUniformType.Sampler3D:     // TODO: remove Texture3D that is not available in OpenGL ES 2
                    case ActiveUniformType.SamplerCube:
                    case ActiveUniformType.IntSampler2D:
                    case ActiveUniformType.IntSampler3D:
                    case ActiveUniformType.IntSamplerCube:
                    case ActiveUniformType.UnsignedIntSampler2D:
                    case ActiveUniformType.UnsignedIntSampler3D:
                    case ActiveUniformType.UnsignedIntSamplerCube:
                        var uniformIndex = GL.GetUniformLocation(ProgramId, uniformName);

                        // 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.RawName == textureName);
                            samplerReflectionIndex =
                                effectReflection.ResourceBindings.FindIndex(x => x.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 [{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.Type      = GetTypeFromActiveUniformType(uniformType);
                        textureReflection.Class     = EffectParameterClass.ShaderResourceView;
                        textureReflection.SlotStart = textureUnitCount;
                        textureReflection.SlotCount = 1;     // TODO: texture arrays

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

                        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);
                effectReflection.ConstantBuffers = effectReflection.ConstantBuffers.Where((cb, i) => validConstantBuffers[i]).ToList();
            }

            GL.UseProgram(currentProgram);
        }
Exemplo n.º 7
0
        private string Compile(string shaderSource, string entryPoint, ShaderStage stage, GlslShaderPlatform shaderPlatform, int shaderVersion, ShaderBytecodeResult shaderBytecodeResult, EffectReflection reflection, IDictionary <int, string> inputAttributeNames, Dictionary <string, int> resourceBindings, string sourceFilename = null)
        {
            if (shaderPlatform == GlslShaderPlatform.OpenGLES && shaderVersion < 300 && renderTargetCount > 1)
            {
                shaderBytecodeResult.Error("OpenGL ES 2 does not support multiple render targets.");
            }

            PipelineStage pipelineStage = PipelineStage.None;

            switch (stage)
            {
            case ShaderStage.Vertex:
                pipelineStage = PipelineStage.Vertex;
                break;

            case ShaderStage.Pixel:
                pipelineStage = PipelineStage.Pixel;
                break;

            case ShaderStage.Geometry:
                shaderBytecodeResult.Error("Geometry stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Hull:
                shaderBytecodeResult.Error("Hull stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Domain:
                shaderBytecodeResult.Error("Domain stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            case ShaderStage.Compute:
                shaderBytecodeResult.Error("Compute stage can't be converted to OpenGL. Only Vertex and Pixel shaders are supported");
                break;

            default:
                shaderBytecodeResult.Error("Unknown shader profile.");
                break;
            }

            if (shaderBytecodeResult.HasErrors)
            {
                return(null);
            }

            Shader glslShader;

            // null entry point means no shader. In that case, we return a default function in HlslToGlslWriter
            // TODO: support that directly in HlslToGlslConvertor?
            if (entryPoint == null)
            {
                glslShader = null;
            }
            else
            {
                // Convert from HLSL to GLSL
                // Note that for now we parse from shader as a string, but we could simply clone effectPass.Shader to avoid multiple parsing.
                var glslConvertor = new ShaderConverter(shaderPlatform, shaderVersion);
                glslShader = glslConvertor.Convert(shaderSource, entryPoint, pipelineStage, sourceFilename, inputAttributeNames, shaderBytecodeResult);

                if (glslShader == null || shaderBytecodeResult.HasErrors)
                {
                    return(null);
                }

                foreach (var constantBuffer in glslShader.Declarations.OfType <ConstantBuffer>())
                {
                    // Update constant buffer itself (first time only)
                    var reflectionConstantBuffer = reflection.ConstantBuffers.FirstOrDefault(x => x.Name == constantBuffer.Name && x.Size == 0);
                    if (reflectionConstantBuffer != null)
                    {
                        // 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 std140 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;
                        }

                        reflectionConstantBuffer.Size = constantBufferOffset;
                    }

                    // Find binding
                    var resourceBindingIndex = reflection.ResourceBindings.IndexOf(x => x.RawName == constantBuffer.Name);
                    if (resourceBindingIndex != -1)
                    {
                        MarkResourceBindingAsUsed(reflection, resourceBindingIndex, stage);
                    }
                }

                foreach (var variable in glslShader.Declarations.OfType <Variable>().Where(x => (x.Qualifiers.Contains(StorageQualifier.Uniform))))
                {
                    // Check if we have a variable that starts or ends with this name (in case of samplers)
                    // TODO: Have real AST support for all the list in Keywords.glsl
                    if (variable.Type.Name.Text.Contains("sampler1D") ||
                        variable.Type.Name.Text.Contains("sampler2D") ||
                        variable.Type.Name.Text.Contains("sampler3D") ||
                        variable.Type.Name.Text.Contains("samplerCube") ||
                        variable.Type.Name.Text.Contains("samplerBuffer"))
                    {
                        // TODO: Make more robust
                        var textureBindingIndex = reflection.ResourceBindings.IndexOf(x => variable.Name.ToString().StartsWith(x.RawName));
                        var samplerBindingIndex = reflection.ResourceBindings.IndexOf(x => variable.Name.ToString().EndsWith(x.RawName));

                        if (textureBindingIndex != -1)
                        {
                            MarkResourceBindingAsUsed(reflection, textureBindingIndex, stage);
                        }

                        if (samplerBindingIndex != -1)
                        {
                            MarkResourceBindingAsUsed(reflection, samplerBindingIndex, stage);
                        }
                    }
                    else
                    {
                        var resourceBindingIndex = reflection.ResourceBindings.IndexOf(x => x.RawName == variable.Name);
                        if (resourceBindingIndex != -1)
                        {
                            MarkResourceBindingAsUsed(reflection, resourceBindingIndex, stage);
                        }
                    }
                }

                if (shaderPlatform == GlslShaderPlatform.Vulkan)
                {
                    // Defines the ordering of resource groups in Vulkan. This is mirrored in the PipelineState
                    var resourceGroups = reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList();

                    // Register "NoSampler", required by HLSL=>GLSL translation to support HLSL such as texture.Load().
                    var noSampler = new EffectResourceBindingDescription {
                        KeyInfo = { KeyName = "NoSampler" }, RawName = "NoSampler", Class = EffectParameterClass.Sampler, SlotStart = -1, SlotCount = 1
                    };
                    reflection.ResourceBindings.Add(noSampler);

                    var bindings = resourceGroups.SelectMany(resourceGroup => reflection.ResourceBindings
                                                             .Where(x => x.ResourceGroup == resourceGroup || (x.ResourceGroup == null && resourceGroup == "Globals"))
                                                             .GroupBy(x => new { KeyName = x.KeyInfo.KeyName, RawName = x.RawName, Class = x.Class, Type = x.Type, SlotCount = x.SlotCount, LogicalGroup = x.LogicalGroup })
                                                             .OrderBy(x => x.Key.Class == EffectParameterClass.ConstantBuffer ? 0 : 1))
                                   .ToList();

                    // Add layout(set, bindings) qualifier to all constant buffers
                    foreach (var constantBuffer in glslShader.Declarations.OfType <ConstantBuffer>())
                    {
                        var layoutBindingIndex = bindings.IndexOf(x => x.Key.RawName == constantBuffer.Name);
                        if (layoutBindingIndex != -1)
                        {
                            var layoutQualifier = constantBuffer.Qualifiers.OfType <Xenko.Core.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                            if (layoutQualifier == null)
                            {
                                layoutQualifier            = new Xenko.Core.Shaders.Ast.Glsl.LayoutQualifier();
                                constantBuffer.Qualifiers |= layoutQualifier;
                            }

                            //layoutQualifier.Layouts.Add(new LayoutKeyValue("set", resourceGroups.IndexOf(resourceGroup)));
                            layoutQualifier.Layouts.Add(new LayoutKeyValue("set", 0));
                            layoutQualifier.Layouts.Add(new LayoutKeyValue("binding", layoutBindingIndex + 1));

                            resourceBindings.Add(bindings[layoutBindingIndex].Key.KeyName, layoutBindingIndex + 1);
                        }
                    }

                    // Add layout(set, bindings) qualifier to all other uniforms
                    foreach (var variable in glslShader.Declarations.OfType <Variable>().Where(x => (x.Qualifiers.Contains(StorageQualifier.Uniform))))
                    {
                        var layoutBindingIndex = bindings.IndexOf(x => variable.Name.Text.StartsWith(x.Key.RawName));

                        if (layoutBindingIndex != -1)
                        {
                            var layoutQualifier = variable.Qualifiers.OfType <Xenko.Core.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                            if (layoutQualifier == null)
                            {
                                layoutQualifier      = new Xenko.Core.Shaders.Ast.Glsl.LayoutQualifier();
                                variable.Qualifiers |= layoutQualifier;
                            }

                            //layoutQualifier.Layouts.Add(new LayoutKeyValue("set", resourceGroups.IndexOf(resourceGroup)));
                            layoutQualifier.Layouts.Add(new LayoutKeyValue("set", 0));
                            layoutQualifier.Layouts.Add(new LayoutKeyValue("binding", layoutBindingIndex + 1));

                            resourceBindings.Add(bindings[layoutBindingIndex].Key.KeyName, layoutBindingIndex + 1);
                        }
                    }
                }
            }

            // Output the result
            var glslShaderWriter = new HlslToGlslWriter(shaderPlatform, shaderVersion, pipelineStage);

            if (shaderPlatform == GlslShaderPlatform.OpenGLES && shaderVersion < 320)
            {
                glslShaderWriter.ExtraHeaders = "#define texelFetchBufferPlaceholder";
            }

            // Write shader
            glslShaderWriter.Visit(glslShader);

            var shaderString = glslShaderWriter.Text;

            // Build shader source
            var glslShaderCode = new StringBuilder();

            // Append some header depending on target
            //if (isOpenGLES)
            //{
            //    if (isOpenGLES3)
            //    {
            //        glslShaderCode
            //            .AppendLine("#version 300 es") // TODO: 310 version?
            //            .AppendLine();
            //    }
            //
            //    if (pipelineStage == PipelineStage.Pixel)
            //        glslShaderCode
            //            .AppendLine("precision highp float;")
            //            .AppendLine();
            //}
            //else
            //{
            //    glslShaderCode
            //        .AppendLine("#version 420")
            //        .AppendLine()
            //        .AppendLine("#define samplerBuffer sampler2D")
            //        .AppendLine("#define isamplerBuffer isampler2D")
            //        .AppendLine("#define usamplerBuffer usampler2D")
            //        .AppendLine("#define texelFetchBuffer(sampler, P) texelFetch(sampler, ivec2((P) & 0xFFF, (P) >> 12), 0)");
            //        //.AppendLine("#define texelFetchBuffer(sampler, P) texelFetch(sampler, P)");
            //}

            glslShaderCode.Append(shaderString);

            var realShaderSource = glslShaderCode.ToString();

            return(realShaderSource);
        }
Exemplo n.º 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);
        }
Exemplo n.º 9
0
 private static void LinkVariable(EffectReflection reflection, string variableName, LocalParameterKey parameterKey, int slotCount)
 {
     var binding = new EffectResourceBindingDescription { KeyInfo = { KeyName = parameterKey.Name }, Class = parameterKey.Type.Class, Type = parameterKey.Type.Type, RawName = variableName, SlotStart = -1, SlotCount = slotCount > 0 ? slotCount : 1, ResourceGroup = parameterKey.ResourceGroup, LogicalGroup = parameterKey.LogicalGroup };
     reflection.ResourceBindings.Add(binding);
 }
Exemplo n.º 10
0
        private EffectResourceBindingDescription GetResourceBinding(SharpDX.D3DCompiler.InputBindingDescription bindingDescriptionRaw, string name, LoggerResult log)
        {
            var paramClass = EffectParameterClass.Object;
            var paramType = EffectParameterType.Void;

            switch (bindingDescriptionRaw.Type)
            {
                case SharpDX.D3DCompiler.ShaderInputType.TextureBuffer:
                    paramType = EffectParameterType.TextureBuffer;
                    paramClass = EffectParameterClass.TextureBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.ConstantBuffer:
                    paramType = EffectParameterType.ConstantBuffer;
                    paramClass = EffectParameterClass.ConstantBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.Texture:
                    paramClass = EffectParameterClass.ShaderResourceView;
                    switch (bindingDescriptionRaw.Dimension)
                    {
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Buffer:
                            paramType = EffectParameterType.Buffer;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1D:
                            paramType = EffectParameterType.Texture1D;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1DArray:
                            paramType = EffectParameterType.Texture1DArray;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D:
                            paramType = EffectParameterType.Texture2D;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DArray:
                            paramType = EffectParameterType.Texture2DArray;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DMultisampled:
                            paramType = EffectParameterType.Texture2DMultisampled;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DMultisampledArray:
                            paramType = EffectParameterType.Texture2DMultisampledArray;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture3D:
                            paramType = EffectParameterType.Texture3D;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.TextureCube:
                            paramType = EffectParameterType.TextureCube;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.TextureCubeArray:
                            paramType = EffectParameterType.TextureCubeArray;
                            break;
                    }
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.Structured:
                    paramClass = EffectParameterClass.ShaderResourceView;
                    paramType = EffectParameterType.StructuredBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.ByteAddress:
                    paramClass = EffectParameterClass.ShaderResourceView;
                    paramType = EffectParameterType.ByteAddressBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWTyped:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    switch (bindingDescriptionRaw.Dimension)
                    {
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Buffer:
                            paramType = EffectParameterType.RWBuffer;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1D:
                            paramType = EffectParameterType.RWTexture1D;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture1DArray:
                            paramType = EffectParameterType.RWTexture1DArray;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D:
                            paramType = EffectParameterType.RWTexture2D;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DArray:
                            paramType = EffectParameterType.RWTexture2DArray;
                            break;
                        case SharpDX.Direct3D.ShaderResourceViewDimension.Texture3D:
                            paramType = EffectParameterType.RWTexture3D;
                            break;
                    }
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWStructured:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    paramType = EffectParameterType.RWStructuredBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWByteAddress:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    paramType = EffectParameterType.RWByteAddressBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewAppendStructured:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    paramType = EffectParameterType.AppendStructuredBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewConsumeStructured:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    paramType = EffectParameterType.ConsumeStructuredBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.UnorderedAccessViewRWStructuredWithCounter:
                    paramClass = EffectParameterClass.UnorderedAccessView;
                    paramType = EffectParameterType.RWStructuredBuffer;
                    break;
                case SharpDX.D3DCompiler.ShaderInputType.Sampler:
                    paramClass = EffectParameterClass.Sampler;
                    paramType = EffectParameterType.Sampler;
                    break;
            }

            var binding = new EffectResourceBindingDescription()
                {
                    KeyInfo =
                        {
                            KeyName = name,
                        },
                    RawName = bindingDescriptionRaw.Name,
                    Class = paramClass,
                    Type = paramType,
                    SlotStart = bindingDescriptionRaw.BindPoint,
                    SlotCount = bindingDescriptionRaw.BindCount,
                };

            return binding;
        }