Пример #1
0
        private Shader(GraphicsDevice device, ShaderStage shaderStage, byte[] shaderStageBytecode)
            : base(device)
        {
            this.stage = shaderStage;

            var shaderStageGl = ConvertShaderStage(shaderStage);

            // Decode shader StageBytecode
            var binarySerializationReader = new BinarySerializationReader(new MemoryStream(shaderStageBytecode));
            var shaderBytecodeData = new OpenGLShaderBytecodeData();
            shaderBytecodeData.Serialize(binarySerializationReader, ArchiveMode.Deserialize);

            using (GraphicsDevice.UseOpenGLCreationContext())
            {
                resourceId = GL.CreateShader(shaderStageGl);

                if (shaderBytecodeData.IsBinary)
                {
                    GL.ShaderBinary(1, ref resourceId, (BinaryFormat)shaderBytecodeData.BinaryFormat, shaderBytecodeData.Binary, shaderBytecodeData.Binary.Length);
                }
                else
                {
                    GL.ShaderSource(resourceId, shaderBytecodeData.Source);
                    GL.CompileShader(resourceId);

                    var log = GL.GetShaderInfoLog(resourceId);

                    int compileStatus;
                    GL.GetShader(resourceId, ShaderParameter.CompileStatus, out compileStatus);

                    if (compileStatus != 1)
                        throw new InvalidOperationException(string.Format("Error while compiling GLSL shader: {0}", log));
                }
            }
        }
Пример #2
0
 internal Shader(GraphicsDevice device, BinaryReader reader)
 {
   this.GraphicsDevice = device;
   this.Stage = reader.ReadBoolean() ? ShaderStage.Vertex : ShaderStage.Pixel;
   int count = (int) reader.ReadUInt16();
   byte[] bytes = reader.ReadBytes(count);
   int length1 = (int) reader.ReadByte();
   this.Samplers = new SamplerInfo[length1];
   for (int index = 0; index < length1; ++index)
   {
     this.Samplers[index].type = (SamplerType) reader.ReadByte();
     this.Samplers[index].index = (int) reader.ReadByte();
     this.Samplers[index].name = reader.ReadString();
     this.Samplers[index].parameter = (int) reader.ReadByte();
   }
   int length2 = (int) reader.ReadByte();
   this.CBuffers = new int[length2];
   for (int index = 0; index < length2; ++index)
     this.CBuffers[index] = (int) reader.ReadByte();
   this._glslCode = Encoding.ASCII.GetString(bytes);
   this.HashKey = Hash.ComputeHash(bytes);
   int length3 = (int) reader.ReadByte();
   this._attributes = new Shader.Attribute[length3];
   for (int index = 0; index < length3; ++index)
   {
     this._attributes[index].name = reader.ReadString();
     this._attributes[index].usage = (VertexElementUsage) reader.ReadByte();
     this._attributes[index].index = (int) reader.ReadByte();
     this._attributes[index].format = reader.ReadInt16();
   }
 }
Пример #3
0
        private Shader(GraphicsDevice device, ShaderStage shaderStage, byte[] shaderBytecode)
            : base(device)
        {
            this.stage = shaderStage;

            switch (shaderStage)
            {
                case ShaderStage.Vertex:
                    NativeDeviceChild = new VertexShader(device.NativeDevice, shaderBytecode);
                    NativeInputSignature = shaderBytecode;
                    break;
                case ShaderStage.Hull:
                    NativeDeviceChild = new HullShader(device.NativeDevice, shaderBytecode);
                    break;
                case ShaderStage.Domain:
                    NativeDeviceChild = new DomainShader(device.NativeDevice, shaderBytecode);
                    break;
                case ShaderStage.Geometry:
                    NativeDeviceChild = new GeometryShader(device.NativeDevice, shaderBytecode);
                    break;
                case ShaderStage.Pixel:
                    NativeDeviceChild = new PixelShader(device.NativeDevice, shaderBytecode);
                    break;
                case ShaderStage.Compute:
                    NativeDeviceChild = new ComputeShader(device.NativeDevice, shaderBytecode);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("shaderStage");
            }
        }
 public static ShaderSamplerSetCommand Create(ShaderStage stage, IEnumerable<SamplerResource> resources = null)
 {
     if (resources == null)
     {
         resources = new SamplerResource[] { };
     }
     return new ShaderSamplerSetCommand
     {
         Stage = stage,
         Samplers = resources.Select(r => r.ID).ToArray(),
     };
 }
Пример #5
0
 public static string GetText(ShaderStage stage)
 {
     switch (stage)
     {
         case ShaderStage.Vertex: return VertexText;
         case ShaderStage.Pixel: return PixelText;
         case ShaderStage.Geometry: return GeometryText;
         case ShaderStage.Hull: return HullText;
         case ShaderStage.Domain: return DomainText;
         case ShaderStage.Compute: return ComputeText;
         default: throw new ArgumentOutOfRangeException("stage");
     }
 }
Пример #6
0
        /// <summary>
        /// Converts the hlsl code into glsl and stores the result as plain text
        /// </summary>
        /// <param name="shaderSource">the hlsl shader</param>
        /// <param name="entryPoint">the entrypoint function name</param>
        /// <param name="stage">the shader pipeline stage</param>
        /// <param name="compilerParameters"></param>
        /// <param name="reflection">the reflection gathered from the hlsl analysis</param>
        /// <param name="sourceFilename">the name of the source file</param>
        /// <returns></returns>
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isOpenGLES = compilerParameters.Get(CompilerParameters.GraphicsPlatformKey) == GraphicsPlatform.OpenGLES;
            var isOpenGLES3 = compilerParameters.Get(CompilerParameters.GraphicsProfileKey) >= GraphicsProfile.Level_10_0;
            var shaderBytecodeResult = new ShaderBytecodeResult();
            byte[] rawData;

            var shader = Compile(shaderSource, entryPoint, stage, isOpenGLES, isOpenGLES3, shaderBytecodeResult, sourceFilename);

            if (shader == null)
                return shaderBytecodeResult;

            if (isOpenGLES)
            {
                // store both ES 2 and ES 3 on OpenGL ES platforms
                var shaderBytecodes = new ShaderLevelBytecode();
                if (isOpenGLES3)
                {
                    shaderBytecodes.DataES3 = shader;
                    shaderBytecodes.DataES2 = null;
                }
                else
                {
                    shaderBytecodes.DataES2 = shader;
                    shaderBytecodes.DataES3 = Compile(shaderSource, entryPoint, stage, true, true, shaderBytecodeResult, sourceFilename);
                }
                using (var stream = new MemoryStream())
                {
                    BinarySerialization.Write(stream, shaderBytecodes);
#if !SILICONSTUDIO_RUNTIME_CORECLR
                    rawData = stream.GetBuffer();
#else
// FIXME: Manu: The call to "ToArray()" might be slower than "GetBuffer()"
                    rawData = stream.ToArray();
#endif
                }
            }
            else
            {
                // store string on OpenGL platforms
                rawData = Encoding.ASCII.GetBytes(shader);
            }
            
            var bytecodeId = ObjectId.FromBytes(rawData);
            var bytecode = new ShaderBytecode(bytecodeId, rawData);
            bytecode.Stage = stage;

            shaderBytecodeResult.Bytecode = bytecode;
            
            return shaderBytecodeResult;
        }
Пример #7
0
        internal Shader(GraphicsDevice device, BinaryReader reader)
        {
            GraphicsDevice = device;

            var isVertexShader = reader.ReadBoolean();
            Stage = isVertexShader ? ShaderStage.Vertex : ShaderStage.Pixel;

            var shaderLength = reader.ReadInt32();
            var shaderBytecode = reader.ReadBytes(shaderLength);

            var samplerCount = (int)reader.ReadByte();
            Samplers = new SamplerInfo[samplerCount];
            for (var s = 0; s < samplerCount; s++)
            {
                Samplers[s].type = (SamplerType)reader.ReadByte();
                Samplers[s].textureSlot = reader.ReadByte();
                Samplers[s].samplerSlot = reader.ReadByte();

				if (reader.ReadBoolean())
				{
					Samplers[s].state = new SamplerState();
					Samplers[s].state.AddressU = (TextureAddressMode)reader.ReadByte();
					Samplers[s].state.AddressV = (TextureAddressMode)reader.ReadByte();
					Samplers[s].state.AddressW = (TextureAddressMode)reader.ReadByte();
                    Samplers[s].state.BorderColor = new Color(
                        reader.ReadByte(), 
                        reader.ReadByte(), 
                        reader.ReadByte(), 
                        reader.ReadByte());
					Samplers[s].state.Filter = (TextureFilter)reader.ReadByte();
					Samplers[s].state.MaxAnisotropy = reader.ReadInt32();
					Samplers[s].state.MaxMipLevel = reader.ReadInt32();
					Samplers[s].state.MipMapLevelOfDetailBias = reader.ReadSingle();
				}

#if OPENGL
                Samplers[s].name = reader.ReadString();
#else
                Samplers[s].name = null;
#endif
                Samplers[s].parameter = reader.ReadByte();
            }

            var cbufferCount = (int)reader.ReadByte();
            CBuffers = new int[cbufferCount];
            for (var c = 0; c < cbufferCount; c++)
                CBuffers[c] = reader.ReadByte();

            PlatformConstruct(reader, isVertexShader, shaderBytecode);
        }
Пример #8
0
		/// <summary>
		/// Construct a ShaderObject defining its main class.
		/// </summary>
		/// <param name="shaderStage">
		/// A <see cref="ShaderStage"/> indicating the shader stage of this ShaderObject.
		/// </param>
		/// <param name="sourcePath">
		/// A <see cref="String"/> that specify the file containing the shader object source strings.
		/// </param>
		protected ShaderObject(ShaderStage shaderStage, string sourcePath) :
			this(shaderStage)
		{
			try {
				if (sourcePath == null)
					throw new ArgumentNullException("sourcePath");
				// Store shader path (for debugging)
				_SourcePath = sourcePath;
			} catch {
				// Avoid finalizer assertion failure (don't call dispose since it's virtual)
				GC.SuppressFinalize(this);
				throw;
			}
		}
Пример #9
0
        private static ShaderType ConvertShaderStage(ShaderStage shaderStage)
        {
            switch (shaderStage)
            {
                case ShaderStage.Pixel:
                    return ShaderType.FragmentShader;
                case ShaderStage.Vertex:
                    return ShaderType.VertexShader;
#if !SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES
                case ShaderStage.Geometry:
                    return ShaderType.GeometryShader;
#endif
                default:
                    throw new NotSupportedException();
            }
        }
Пример #10
0
 internal Shader(GraphicsDevice device, BinaryReader reader)
 {
   this.GraphicsDevice = device;
   this.Stage = reader.ReadBoolean() ? ShaderStage.Vertex : ShaderStage.Pixel;
   int count = (int) reader.ReadUInt16();
   byte[] bytes = reader.ReadBytes(count);
   int length1 = (int) reader.ReadByte();
   this.Samplers = new SamplerInfo[length1];
   for (int index = 0; index < length1; ++index)
   {
     this.Samplers[index].type = (SamplerType) reader.ReadByte();
     this.Samplers[index].textureSlot = (int) reader.ReadByte();
     this.Samplers[index].samplerSlot = (int) reader.ReadByte();
     if (reader.ReadBoolean())
     {
       this.Samplers[index].state = new SamplerState();
       this.Samplers[index].state.AddressU = (TextureAddressMode) reader.ReadByte();
       this.Samplers[index].state.AddressV = (TextureAddressMode) reader.ReadByte();
       this.Samplers[index].state.AddressW = (TextureAddressMode) reader.ReadByte();
       this.Samplers[index].state.Filter = (TextureFilter) reader.ReadByte();
       this.Samplers[index].state.MaxAnisotropy = reader.ReadInt32();
       this.Samplers[index].state.MaxMipLevel = reader.ReadInt32();
       this.Samplers[index].state.MipMapLevelOfDetailBias = reader.ReadSingle();
     }
     this.Samplers[index].name = reader.ReadString();
     this.Samplers[index].parameter = (int) reader.ReadByte();
   }
   int length2 = (int) reader.ReadByte();
   this.CBuffers = new int[length2];
   for (int index = 0; index < length2; ++index)
     this.CBuffers[index] = (int) reader.ReadByte();
   this._glslCode = Encoding.ASCII.GetString(bytes);
   this.HashKey = Hash.ComputeHash(bytes);
   int length3 = (int) reader.ReadByte();
   this._attributes = new Shader.Attribute[length3];
   for (int index = 0; index < length3; ++index)
   {
     this._attributes[index].name = reader.ReadString();
     this._attributes[index].usage = (VertexElementUsage) reader.ReadByte();
     this._attributes[index].index = (int) reader.ReadByte();
     this._attributes[index].format = reader.ReadInt16();
   }
 }
Пример #11
0
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, ShaderMixinParameters compilerParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isDebug = compilerParameters.Get(CompilerParameters.DebugKey);
            var profile = compilerParameters.Get(CompilerParameters.GraphicsProfileKey);
            
            var shaderModel = ShaderStageToString(stage) + "_" + ShaderProfileFromGraphicsProfile(profile);

            var shaderFlags = ShaderFlags.None;
            if (isDebug)
            {
                shaderFlags = ShaderFlags.OptimizationLevel0 | ShaderFlags.Debug;
            }

            SharpDX.Configuration.ThrowOnShaderCompileError = false;

            // Compile using D3DCompiler
            var compilationResult = SharpDX.D3DCompiler.ShaderBytecode.Compile(shaderSource, entryPoint, shaderModel, shaderFlags, EffectFlags.None, null, null, sourceFilename);

            var byteCodeResult = new ShaderBytecodeResult();

            if (compilationResult.HasErrors)
            {
                // Log compilation errors
                byteCodeResult.Error(compilationResult.Message);
            }
            else
            {
                // As effect bytecode binary can changed when having debug infos (with d3dcompiler_47), we are calculating a bytecodeId on the stripped version
                var rawData = compilationResult.Bytecode.Strip(StripFlags.CompilerStripDebugInformation | StripFlags.CompilerStripReflectionData);
                var bytecodeId = ObjectId.FromBytes(rawData);
                byteCodeResult.Bytecode = new ShaderBytecode(bytecodeId, compilationResult.Bytecode.Data) { Stage = stage };

                // If compilation succeed, then we can update reflection.
                UpdateReflection(byteCodeResult.Bytecode, reflection, byteCodeResult);

                if (!string.IsNullOrEmpty(compilationResult.Message))
                {
                    byteCodeResult.Warning(compilationResult.Message);
                }
            }

            return byteCodeResult;
        }
 public static ShaderStageFlags Convert(ShaderStage stage)
 {
     switch (stage)
     {
         case ShaderStage.Vertex:
             return ShaderStageFlags.Vertex;
         case ShaderStage.Hull:
             return ShaderStageFlags.TessellationControl;
         case ShaderStage.Domain:
             return ShaderStageFlags.TessellationEvaluation;
         case ShaderStage.Geometry:
             return ShaderStageFlags.Geometry;
         case ShaderStage.Pixel:
             return ShaderStageFlags.Fragment;
         case ShaderStage.Compute:
             return ShaderStageFlags.Compute;
         default:
             throw new ArgumentOutOfRangeException();
     }
 }
Пример #13
0
        internal void PlatformApply(GraphicsDevice device, ShaderStage stage, int slot)
        {
            if (_cbuffer == null)
                PlatformInitialize();

            // NOTE: We make the assumption here that the caller has
            // locked the d3dContext for us to use.
            var d3dContext = GraphicsDevice._d3dContext;

            // Update the hardware buffer.
            if (_dirty)
            {
                d3dContext.UpdateSubresource(_buffer, _cbuffer);
                _dirty = false;
            }
            
            // Set the buffer to the right stage.
            if (stage == ShaderStage.Vertex)
                d3dContext.VertexShader.SetConstantBuffer(slot, _cbuffer);
            else
                d3dContext.PixelShader.SetConstantBuffer(slot, _cbuffer);
        }
Пример #14
0
        static string GenerateMacros(ShaderStage stage)
        {
            var builder = new StringBuilder(1 << 14);

            #region General
            builder.AppendLine(@"
            #define OGL
            #define OGL3
            #define OGL4

            #define static");
            #endregion

            #region Types
            Vectors(T.Float, builder, "#define float{1} {0}");
            Vectors(T.Double, builder, "#define double{1} {0}");
            Vectors(T.Int, builder, "#define int{1} {0}");
            Vectors(T.Uint, builder, "#define uint{1} {0}");
            Vectors(T.Bool, builder, "#define bool{1} {0}");

            Matrices(T.Float, builder, "#define float{1}x{2} {0}");
            Matrices(T.Double, builder, "#define double{1}x{2} {0}");
            #endregion

            #region all
            Scalars(T.Float | /*T.Double |*/ T.Int | T.Uint, builder, type =>
                string.Format("bool all({0} arg) {{ return arg != {0}(0); }}", type));

            AggregateVectors(T.Float | /*T.Double |*/ T.Int | T.Uint, builder,
                type => string.Format("bool all({0} arg) {{ return", type),
                type => string.Format(" arg.x != {0}(0)", GetBaseType(type)),
                (type, i) => string.Format(" && arg.{0} != {1}(0)", VectorElement(i), GetBaseType(type)),
                type => "; }");
            /*
            AggregateMatrices(T.Float | T.Double, builder,
                type => string.Format("bool all({0} arg) {{ return", type),
                type => " arg[0][0] != 0.0",
                (type, r, c) => string.Format(" && arg[{0}][{1}] != 0.0", r, c),
                type => "; }");*/
            #endregion

            #region any
            Scalars(T.Float | /*T.Double |*/ T.Int | T.Uint, builder, type =>
                string.Format("bool any({0} arg) {{ return arg != {0}(0); }}", type));

            AggregateVectors(T.Float | /*T.Double |*/ T.Int | T.Uint, builder,
                type => string.Format("bool any({0} arg) {{ return", type),
                type => string.Format(" arg.x != {0}(0)", GetBaseType(type)),
                (type, i) => string.Format(" || arg.{0} != {1}(0)", VectorElement(i), GetBaseType(type)),
                type => "; }");
            /*
            AggregateMatrices(T.Float | T.Double, builder,
                type => string.Format("bool any({0} arg) {{ return", type),
                type => " arg[0][0] != 0.0",
                (type, r, c) => string.Format(" || arg[{0}][{1}] != 0.0", r, c),
                type => "; }");*/
            #endregion

            #region atan2
            builder.AppendLine("#define atan2(Y, X) atan(Y, X)");
            #endregion

            #region clip
            if (stage == ShaderStage.Pixel)
            {
                builder.AppendLine("void clip(float arg) { if (arg < 0.0) { discard; } }");

                AggregateVectors(T.Float, builder,
                    type => string.Format("void clip({0} arg) {{ if (", type),
                    type => "arg.x < 0.0",
                    (type, i) => string.Format(" || arg.{0} < 0.0", VectorElement(i)),
                    type => ") { discard; } }");
                /*
                AggregateMatrices(T.Float, builder,
                    type => string.Format("void clip({0} arg) {{ if (", type),
                    type => "arg[0][0] < 0.0",
                    (type, r, c) => string.Format(" || arg[{0}][{1}] < 0.0", r, c),
                    type => ") { discard; } }");*/
            }
            #endregion

            #region ddx ddy
            if (stage == ShaderStage.Pixel)
            {
                builder.AppendLine("#define ddx dFdx");
                builder.AppendLine("#define ddy dFdy");
            }
            #endregion

            #region dot
            AggregateVectors(T.Int, builder,
                type => string.Format("int dot({0} arg1, {0} arg2) {{ return ", type),
                type => "arg1.x * arg2.x",
                (type, i) => string.Format(" + arg1.{0} * arg2.{0}", VectorElement(i)),
                type => "; }");
            #endregion

            #region fmod
            builder.AppendLine("#define fmod(X, Y) (X - Y * trunc(X / Y))");
            #endregion

            #region frac
            builder.AppendLine("#define frac(X) fract(X)");
            #endregion

            #region frexp
            builder.AppendLine("float frexp(float x, out float e) { float absx = abs(x); e = ceil(log2(absx)); return absx * exp2(-e); }");
            Vectors(T.Float, builder, "{0} frexp({0} x, out {0} e) {{ {0} absx = abs(x); e = ceil(log2(absx)); return absx * exp2(-e); }}");
            //Matrices(T.Float, builder, "{0} frexp({0} x, out {0} e) {{ {0} absx = abs(x); e = ceil(log2(absx)); return absx * exp2(-e); }}");
            #endregion

            #region GetRenderTargetSampleCount
            if (stage == ShaderStage.Pixel)
            {
                builder.AppendLine("#define GetRenderTargetSampleCount() gl_NumSamples");
                //builder.AppendLine("uint GetRenderTargetSampleCount() { return gl_NumSamples; }");
            }
            #endregion

            #region GetRenderTargetSamplePosition
            if (stage == ShaderStage.Pixel)
            {
                builder.AppendLine("#define GetRenderTargetSamplePosition() gl_SamplePosition ");
                //builder.AppendLine("uint GetRenderTargetSampleCount() { return gl_NumSamples; }");
            }
            #endregion

            #region isfinite
            builder.AppendLine("#define isfinite(X) (!isinf(X))");
            #endregion

            #region ldexp
            builder.AppendLine("float ldexp(float x, float e) { return x * exp2(e); } ");
            Vectors(T.Float, builder, "{0} ldexp({0} x, {0} e) {{ return x * exp2(e); }}");
            //Matrices(T.Float, builder, "{0} ldexp({0} x, {0} e) {{ return x * exp2(e); }}");
            #endregion

            #region lerp
            builder.AppendLine("#define lerp mix");
            #endregion

            #region lit
            builder.AppendLine("float4 lit(float n_dot_l, float n_dot_h, float m) { float diffuse = max(0.0, n_dot_l); float specular; if (diffuse < 0.0) specular = 0.0; else specular = pow(n_dot_h, m); return float4(1.0, diffuse, specular, 1.0); } ");
            #endregion

            #region log10
            builder.AppendLine("#define log10(X) (log2(X) / log2(10.0))");
            #endregion

            #region modf
            builder.AppendLine("float modf(float x, out int ip) { float ipf; float result = modf(x, ipf); ip = int(ipf); return result; }");
            Vectors(T.Float, builder, (type, size) => string.Format("{0} modf({0} x, out int{1} ip) {{ {0} ipf; {0} result = modf(x, ipf); ip = int{1}(ipf); return result; }}", type, size));
            #endregion

            #region mul
            builder.AppendLine("#define mul(A, B) (A * B)");
            #endregion

            #region noise
            //builder.AppendLine("#define noise noise1");
            #endregion

            #region rsqrt
            builder.AppendLine("#define rsqrt inversesqrt");
            #endregion

            #region sqrt
            builder.AppendLine("#define saturate(x) clamp(x, 0.0, 1.0)");
            #endregion

            #region sincos
            builder.AppendLine("void sincos(float x, out float s, out float c) { s = sin(x); c = cos(x); }");
            Vectors(T.Float, builder, "void sincos({0} x, out {0} s, out {0} c) {{ s = sin(x); c = cos(x); }}");
            #endregion

            #region Textures
            builder.AppendLine(@"
            #define calculateLevelOfDetail(T, C) textureQueryLod(T, C).x
            #define gather(T, C) textureGather(T, C)
            #define gatherOffset(T, C, O) textureGatherOffset(T, C, O)
            #define gatherCmp(T, C, V) textureGather(T, C, V)
            #define gatherCmpOffset(T, C, V, O) textureGatherOffset(T, C, V, O)
            #define getSize(T) textureSize(T)
            #define BS_TEXTURE_LOAD_DIMENSION(T) BS_TEXTURE_LOAD_DIMENSION_##T
            #define load(T, C) BS_TEXTURE_LOAD(BS_TEXTURE_LOAD_DIMENSION(T), T, C)
            #define BS_TEXTURE_LOAD(D, T, C) BS_TEXTURE_LOAD_##D(T, C)
            #define BS_TEXTURE_LOAD_2(T, C) texelFetch(T, C.x, C.y)
            #define BS_TEXTURE_LOAD_3(T, C) texelFetch(T, C.xy, C.z)
            #define BS_TEXTURE_LOAD_4(T, C) texelFetch(T, C.xyz, C.w)
            #define loadOffset(T, C, O) BS_TEXTURE_LOAD_OFFSET(BS_TEXTURE_LOAD_DIMENSION(T), T, C, O)
            #define BS_TEXTURE_LOAD_OFFSET(D, T, C, O) BS_TEXTURE_LOAD_OFFSET_##D(T, C, O)
            #define BS_TEXTURE_LOAD_OFFSET_2(T, C, O) texelFetchOffset(T, C.x, C.y, O)
            #define BS_TEXTURE_LOAD_OFFSET_3(T, C, O) texelFetchOffset(T, C.xy, C.z, O)
            #define BS_TEXTURE_LOAD_OFFSET_4(T, C, O) texelFetchOffset(T, C.xyz, C.w, O)
            #define loadSample(T, C, S) texelFetch(T, C, S)
            #define sample(T, C) texture(T, C)
            #define sampleOffset(T, C, O) textureOffset(T, C, O)
            #define sampleBias(T, C, B) texture(T, C, B)
            #define sampleBiasOffset(T, C, B, O) textureOffset(T, C, O, B)
            #define BS_TEXTURE_SAMPLE_CMP_DIMENSION(T) BS_TEXTURE_SAMPLE_CMP_DIMENSION_##T
            #define sampleCmp(T, C, V) BS_TEXTURE_SAMPLE_CMP(BS_TEXTURE_SAMPLE_CMP_DIMENSION(T), T, C, V)
            #define BS_TEXTURE_SAMPLE_CMP(D, T, C, V) BS_TEXTURE_SAMPLE_CMP_##D(T, C, V)
            #define BS_TEXTURE_SAMPLE_CMP_1(T, C, V) uint(texture(t, float3(l, 0.0, v)))
            #define BS_TEXTURE_SAMPLE_CMP_2(T, C, V) uint(texture(t, float3(l, v)))
            #define BS_TEXTURE_SAMPLE_CMP_3(T, C, V) uint(texture(t, float4(l, v)))
            #define BS_TEXTURE_SAMPLE_CMP_4(T, C, V) uint(texture(t, l, v))
            #define sampleCmpOffset(T, C, V, O) BS_TEXTURE_SAMPLE_CMP_OFFSET(BS_TEXTURE_SAMPLE_CMP_DIMENSION(T), T, C, V, O)
            #define BS_TEXTURE_SAMPLE_CMP_OFFSET(D, T, C, V, O) BS_TEXTURE_SAMPLE_CMP_OFFSET_##D(T, C, V, O)
            #define BS_TEXTURE_SAMPLE_CMP_OFFSET_1(T, C, V, O) uint(textureOffset(T, float3(C, 0.0, V), O)))
            #define BS_TEXTURE_SAMPLE_CMP_OFFSET_2(T, C, V, O) uint(textureOffset(T, float3(C, V), O))
            #define BS_TEXTURE_SAMPLE_CMP_OFFSET_3(T, C, V, O) uint(textureOffset(T, float4(C, V), O))
            #define sampleCmpLevelZero(T, C, V) BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO(BS_TEXTURE_SAMPLE_CMP_DIMENSION(T), T, C, V)
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO(D, T, C, V) BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_##D(T, C, V)
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_1(T, C, V) uint(texture(t, float3(l, 0.0, v)))
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_2(T, C, V) uint(texture(t, float3(l, v)))
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_3(T, C, V) uint(texture(t, float4(l, v)))
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_4(T, C, V) uint(texture(t, l, v))
            #define sampleCmpLevelZeroOffset(T, C, V, O) BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_OFFSET(BS_TEXTURE_SAMPLE_CMP_DIMENSION(T), T, C, V, O)
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_OFFSET(D, T, C, V, O) BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_OFFSET_##D(T, C, V, O)
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_OFFSET_1(T, C, V, O) uint(textureLodOffset(T, float3(C, 0.0, V), 0.0, O))
            #define BS_TEXTURE_SAMPLE_CMP_LEVEL_ZERO_OFFSET_2(T, C, V, O) uint(textureLodOffset(T, float3(C, V), 0.0, O))
            #define sampleGrad(T, C, X, Y) textureGrad(T, C, X, Y)
            #define sampleGradOffset(T, C, X, Y, O) textureGradOffset(T, C, X, Y, O)
            #define sampleLod(T, C, L) textureLod(T, C, L)
            #define sampleLodOffset(T, C, L, O) textureLodOffset(T, C, L, O)
            ");
            #endregion

            return builder.ToString();
        }
Пример #15
0
 public static MethodDefinition GetEntryPoint(this Shader shader, ShaderStage type)
 {
     return(shader.Declarations.OfType <MethodDefinition>().FirstOrDefault(f => f.Attributes.OfType <AttributeDeclaration>().Any(a => a.Name == "EntryPoint" && (string)a.Parameters[0].Value == type.ToString())));
 }
Пример #16
0
        static void WriteIOAndCode(StringBuilder builder, CVertexShader shader, ShaderStage outputStage)
        {
            var reflection = shader.Reflection;

            WriteCodeLines(builder, reflection.CodeGlobalLines);
            builder.AppendLine();

            WriteSimpleIOBlock(builder, reflection.Input, "INPUT", "in", OutputPrefixForStage(ShaderStage.Vertex));
            WriteSimpleIOBlock(builder, reflection.Output, "OUTPUT", "out", OutputPrefixForStage(outputStage));
            WriteFunction(builder, "main", null, reflection.CodeMainLines, outputStage == ShaderStage.Pixel ? PositionAdjustment : null);
        }
Пример #17
0
        private string Compile(string shaderSource, string entryPoint, ShaderStage stage, bool isOpenGLES, bool isOpenGLES3, ShaderBytecodeResult shaderBytecodeResult, string sourceFilename = null)
        {
            if (isOpenGLES && !isOpenGLES3 && 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;

            string shaderString = null;
            var generateUniformBlocks = isOpenGLES && isOpenGLES3;

            // null entry point for pixel shader means no pixel shader. In that case, we return a default function.
            if (entryPoint == null && stage == ShaderStage.Pixel && isOpenGLES)
            {
                shaderString = "out float fragmentdepth; void main(){ fragmentdepth = gl_FragCoord.z; }";
            }
            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(isOpenGLES, isOpenGLES3);
                var glslShader = glslConvertor.Convert(shaderSource, entryPoint, pipelineStage, sourceFilename, shaderBytecodeResult);

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

                // Add std140 layout
                foreach (var constantBuffer in glslShader.Declarations.OfType<ConstantBuffer>())
                {
                    if (isOpenGLES3) // TODO: for OpenGL too?
                    {
                        var layoutQualifier = constantBuffer.Qualifiers.OfType<SiliconStudio.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                        if (layoutQualifier == null)
                        {
                            layoutQualifier = new SiliconStudio.Shaders.Ast.Glsl.LayoutQualifier();
                            constantBuffer.Qualifiers |= layoutQualifier;
                        }
                        layoutQualifier.Layouts.Add(new LayoutKeyValue("std140"));
                    }
                    else
                    {
                        constantBuffer.Qualifiers |= new LayoutQualifier(new LayoutKeyValue("std140"));
                    }
                }

                // Output the result
                var glslShaderWriter = new HlslToGlslWriter();

                if (isOpenGLES)
                {
                    glslShaderWriter.TrimFloatSuffix = true;

                    glslShaderWriter.GenerateUniformBlocks = generateUniformBlocks;

                    if (!isOpenGLES3)
                    {
                        foreach (var variable in glslShader.Declarations.OfType<Variable>())
                        {
                            if (variable.Qualifiers.Contains(ParameterQualifier.In))
                            {
                                variable.Qualifiers.Values.Remove(ParameterQualifier.In);
                                // "in" becomes "attribute" in VS, "varying" in other stages
                                variable.Qualifiers.Values.Add(
                                    pipelineStage == PipelineStage.Vertex
                                        ? global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Attribute
                                        : global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                            }
                            if (variable.Qualifiers.Contains(ParameterQualifier.Out))
                            {
                                variable.Qualifiers.Values.Remove(ParameterQualifier.Out);
                                variable.Qualifiers.Values.Add(global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                            }
                        }
                    }
                }

                // Write shader
                glslShaderWriter.Visit(glslShader);

                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();
            }

            if ((!isOpenGLES || isOpenGLES3) && pipelineStage == PipelineStage.Pixel && renderTargetCount > 0)
            {
                // TODO: identifiers starting with "gl_" should be reserved. Compilers usually accept them but it may should be prevented.
                glslShaderCode
                    .AppendLine("#define gl_FragData _glesFragData")
                    .AppendLine("out vec4 gl_FragData[" + renderTargetCount + "];")
                    .AppendLine();
            }

            glslShaderCode.Append(shaderString);

            var realShaderSource = glslShaderCode.ToString();

#if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
            // optimize shader
            try
            {
                var optShaderSource = RunOptimizer(shaderBytecodeResult, realShaderSource, isOpenGLES, isOpenGLES3, pipelineStage == PipelineStage.Vertex);
                if (!String.IsNullOrEmpty(optShaderSource))
                    realShaderSource = optShaderSource;
            }
            catch (Exception e)
            {
                shaderBytecodeResult.Warning("Could not run GLSL optimizer:\n{0}", e.Message);
            }
#else
            shaderBytecodeResult.Warning("GLSL optimized has not been executed because it is currently not supported on this platform.");
#endif

            return realShaderSource;
        }
Пример #18
0
 public VertexColorMaterialSlot(int slotId, string displayName, string shaderOutputName,
                                ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
     : base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden)
 {
 }
Пример #19
0
 static void WriteLayout(StringBuilder builder, CVertexShader shader, ShaderStage outputStage)
 {
 }
Пример #20
0
 private Shader(GraphicsDevice device, ShaderStage shaderStage, byte[] shaderBytecode)
     : base(device)
 {
     throw new NotImplementedException();
 }
Пример #21
0
        internal Shader(GraphicsDevice device, BinaryReader reader)
        {
            GraphicsDevice = device;

            var isVertexShader = reader.ReadBoolean();
            Stage = isVertexShader ? ShaderStage.Vertex : ShaderStage.Pixel;

            var shaderLength = reader.ReadInt32();
            var shaderBytecode = reader.ReadBytes(shaderLength);

            var samplerCount = (int)reader.ReadByte();
            Samplers = new SamplerInfo[samplerCount];
            for (var s = 0; s < samplerCount; s++)
            {
                Samplers[s].type = (SamplerType)reader.ReadByte();
                Samplers[s].textureSlot = reader.ReadByte();
                Samplers[s].samplerSlot = reader.ReadByte();

				if (reader.ReadBoolean())
				{
					Samplers[s].state = new SamplerState();
					Samplers[s].state.AddressU = (TextureAddressMode)reader.ReadByte();
					Samplers[s].state.AddressV = (TextureAddressMode)reader.ReadByte();
					Samplers[s].state.AddressW = (TextureAddressMode)reader.ReadByte();
					Samplers[s].state.Filter = (TextureFilter)reader.ReadByte();
					Samplers[s].state.MaxAnisotropy = reader.ReadInt32();
					Samplers[s].state.MaxMipLevel = reader.ReadInt32();
					Samplers[s].state.MipMapLevelOfDetailBias = reader.ReadSingle();
				}

#if OPENGL
                Samplers[s].name = reader.ReadString();
#else
                Samplers[s].name = null;
#endif
                Samplers[s].parameter = reader.ReadByte();
            }

            var cbufferCount = (int)reader.ReadByte();
            CBuffers = new int[cbufferCount];
            for (var c = 0; c < cbufferCount; c++)
                CBuffers[c] = reader.ReadByte();

#if DIRECTX

            _shaderBytecode = shaderBytecode;

            // We need the bytecode later for allocating the
            // input layout from the vertex declaration.
            Bytecode = shaderBytecode;
                
            HashKey = MonoGame.Utilities.Hash.ComputeHash(Bytecode);

            if (isVertexShader)
                CreateVertexShader();
            else
                CreatePixelShader();

#endif // DIRECTX

#if OPENGL
            _glslCode = System.Text.Encoding.ASCII.GetString(shaderBytecode);

            HashKey = MonoGame.Utilities.Hash.ComputeHash(shaderBytecode);

            var attributeCount = (int)reader.ReadByte();
            _attributes = new Attribute[attributeCount];
            for (var a = 0; a < attributeCount; a++)
            {
                _attributes[a].name = reader.ReadString();
                _attributes[a].usage = (VertexElementUsage)reader.ReadByte();
                _attributes[a].index = reader.ReadByte();
                _attributes[a].format = reader.ReadInt16();
            }

#endif // OPENGL
        }
Пример #22
0
 public void PushConstant <T>(GraphicsPipeline pipelineLayout, ShaderStage stageFlags, T data, uint offset = 0) where T : unmanaged
 {
     vkCmdPushConstants(handle, pipelineLayout._pipelineLayout, stageFlags.StageToVkShaderStageFlags(), offset, (uint)Interop.SizeOf <T>(), (void *)&data /*Interop.AllocToPointer<T>(ref data)*/);
 }
Пример #23
0
        /// <summary>
        ///     Sets a constant buffer to the shader pipeline.
        /// </summary>
        /// <param name="stage">The shader stage.</param>
        /// <param name="slot">The binding slot.</param>
        /// <param name="buffer">The constant buffer to set.</param>
        internal void SetConstantBuffer(ShaderStage stage, int slot, Buffer buffer)
        {
            if (stage == ShaderStage.None)
                throw new ArgumentException("Cannot use Stage.None", "stage");

            int stageIndex = (int)stage - 1;

            int slotIndex = stageIndex * ConstantBufferCount + slot;
            if (constantBuffers[slotIndex] != buffer)
            {
                constantBuffers[slotIndex] = buffer;
                shaderStages[stageIndex].SetConstantBuffer(slot, buffer != null ? buffer.NativeBuffer : null);
            }
        }
Пример #24
0
 public UVMaterialSlot(int slotId, string displayName, string shaderOutputName, UVChannel channel,
                       ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
     : base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, shaderStage, hidden)
 {
     this.channel = channel;
 }
Пример #25
0
 public PositionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
                             ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
     : base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
 {
 }
Пример #26
0
 public void UpdateRenderScale(ShaderStage stage, ReadOnlySpan <float> scales, int textureCount, int imageCount)
 {
     _renderer.New <UpdateRenderScaleCommand>().Set(stage, _renderer.CopySpan(scales.Slice(0, textureCount + imageCount)), textureCount, imageCount);
     _renderer.QueueCommand();
 }
Пример #27
0
        private string Compile(string shaderSource, string entryPoint, ShaderStage stage, bool isOpenGLES, bool isOpenGLES3, ShaderBytecodeResult shaderBytecodeResult, string sourceFilename = null)
        {
            if (isOpenGLES && !isOpenGLES3 && 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);
            }

            string shaderString          = null;
            var    generateUniformBlocks = isOpenGLES && isOpenGLES3;

            // null entry point for pixel shader means no pixel shader. In that case, we return a default function.
            if (entryPoint == null && stage == ShaderStage.Pixel && isOpenGLES)
            {
                shaderString = "void main(){}";
            }
            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(isOpenGLES, isOpenGLES3);
                var glslShader    = glslConvertor.Convert(shaderSource, entryPoint, pipelineStage, sourceFilename, shaderBytecodeResult);

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

                // Add std140 layout
                foreach (var constantBuffer in glslShader.Declarations.OfType <ConstantBuffer>())
                {
                    if (isOpenGLES3) // TODO: for OpenGL too?
                    {
                        var layoutQualifier = constantBuffer.Qualifiers.OfType <SiliconStudio.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                        if (layoutQualifier == null)
                        {
                            layoutQualifier            = new SiliconStudio.Shaders.Ast.Glsl.LayoutQualifier();
                            constantBuffer.Qualifiers |= layoutQualifier;
                        }
                        layoutQualifier.Layouts.Add(new LayoutKeyValue("std140"));
                    }
                    else
                    {
                        constantBuffer.Qualifiers |= new LayoutQualifier(new LayoutKeyValue("std140"));
                    }
                }

                // Output the result
                var glslShaderWriter = new HlslToGlslWriter();

                if (isOpenGLES)
                {
                    glslShaderWriter.TrimFloatSuffix = true;

                    glslShaderWriter.GenerateUniformBlocks = generateUniformBlocks;

                    if (!isOpenGLES3)
                    {
                        foreach (var variable in glslShader.Declarations.OfType <Variable>())
                        {
                            if (variable.Qualifiers.Contains(ParameterQualifier.In))
                            {
                                variable.Qualifiers.Values.Remove(ParameterQualifier.In);
                                // "in" becomes "attribute" in VS, "varying" in other stages
                                variable.Qualifiers.Values.Add(
                                    pipelineStage == PipelineStage.Vertex
                                        ? global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Attribute
                                        : global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                            }
                            if (variable.Qualifiers.Contains(ParameterQualifier.Out))
                            {
                                variable.Qualifiers.Values.Remove(ParameterQualifier.Out);
                                variable.Qualifiers.Values.Add(global::SiliconStudio.Shaders.Ast.Glsl.ParameterQualifier.Varying);
                            }
                        }
                    }
                }

                // Write shader
                glslShaderWriter.Visit(glslShader);

                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 (generateUniformBlocks) // TODO: is it really needed? It produces only a warning.
                {
                    glslShaderCode
                    .AppendLine("#extension GL_ARB_gpu_shader5 : enable")
                    .AppendLine();
                }

                if (pipelineStage == PipelineStage.Pixel)
                {
                    glslShaderCode
                    .AppendLine("precision highp float;")
                    .AppendLine();
                }
            }
            else
            {
                glslShaderCode
                .AppendLine("#version 420")
                .AppendLine();
            }

            if ((!isOpenGLES || isOpenGLES3) && pipelineStage == PipelineStage.Pixel && renderTargetCount > 0)
            {
                // TODO: identifiers starting with "gl_" should be reserved. Compilers usually accept them but it may should be prevented.
                glslShaderCode
                .AppendLine("out vec4 gl_FragData[" + renderTargetCount + "];")
                .AppendLine();
            }

            glslShaderCode.Append(shaderString);

            var realShaderSource = glslShaderCode.ToString();

            // optimize shader
            var optShaderSource = RunOptimizer(realShaderSource, isOpenGLES, isOpenGLES3, pipelineStage == PipelineStage.Vertex);

            if (!String.IsNullOrEmpty(optShaderSource))
            {
                realShaderSource = optShaderSource;
            }

            return(realShaderSource);
        }
Пример #28
0
        internal Shader(GraphicsDevice device, BinaryReader reader)
        {
            GraphicsDevice = device;

            var isVertexShader = reader.ReadBoolean();

            Stage = isVertexShader ? ShaderStage.Vertex : ShaderStage.Pixel;

            var shaderLength   = reader.ReadInt32();
            var shaderBytecode = reader.ReadBytes(shaderLength);

            var samplerCount = (int)reader.ReadByte();

            Samplers = new SamplerInfo[samplerCount];
            for (var s = 0; s < samplerCount; s++)
            {
                Samplers[s].type        = (SamplerType)reader.ReadByte();
                Samplers[s].textureSlot = reader.ReadByte();
                Samplers[s].samplerSlot = reader.ReadByte();

                if (reader.ReadBoolean())
                {
                    Samplers[s].state                         = new SamplerState();
                    Samplers[s].state.AddressU                = (TextureAddressMode)reader.ReadByte();
                    Samplers[s].state.AddressV                = (TextureAddressMode)reader.ReadByte();
                    Samplers[s].state.AddressW                = (TextureAddressMode)reader.ReadByte();
                    Samplers[s].state.Filter                  = (TextureFilter)reader.ReadByte();
                    Samplers[s].state.MaxAnisotropy           = reader.ReadInt32();
                    Samplers[s].state.MaxMipLevel             = reader.ReadInt32();
                    Samplers[s].state.MipMapLevelOfDetailBias = reader.ReadSingle();
                }

#if OPENGL
                Samplers[s].name = reader.ReadString();
#else
                Samplers[s].name = null;
#endif
                Samplers[s].parameter = reader.ReadByte();
            }

            var cbufferCount = (int)reader.ReadByte();
            CBuffers = new int[cbufferCount];
            for (var c = 0; c < cbufferCount; c++)
            {
                CBuffers[c] = reader.ReadByte();
            }

#if DIRECTX
            _shaderBytecode = shaderBytecode;

            // We need the bytecode later for allocating the
            // input layout from the vertex declaration.
            Bytecode = shaderBytecode;

            HashKey = MonoGame.Utilities.Hash.ComputeHash(Bytecode);

            if (isVertexShader)
            {
                CreateVertexShader();
            }
            else
            {
                CreatePixelShader();
            }
#endif // DIRECTX

#if OPENGL
            _glslCode = System.Text.Encoding.ASCII.GetString(shaderBytecode);

            HashKey = MonoGame.Utilities.Hash.ComputeHash(shaderBytecode);

            var attributeCount = (int)reader.ReadByte();
            _attributes = new Attribute[attributeCount];
            for (var a = 0; a < attributeCount; a++)
            {
                _attributes[a].name   = reader.ReadString();
                _attributes[a].usage  = (VertexElementUsage)reader.ReadByte();
                _attributes[a].index  = reader.ReadByte();
                _attributes[a].format = reader.ReadInt16();
            }
#endif // OPENGL
        }
Пример #29
0
 /// <summary>
 ///     Sets a shader resource view to the shader pipeline.
 /// </summary>
 /// <param name="stage">The shader stage.</param>
 /// <param name="slot">The binding slot.</param>
 /// <param name="shaderResourceView">The shader resource view.</param>
 internal void SetShaderResourceView(ShaderStage stage, int slot, GraphicsResource shaderResourceView)
 {
     shaderStages[(int)stage - 1].SetShaderResource(slot, shaderResourceView != null ? shaderResourceView.NativeShaderResourceView : null);
 }
Пример #30
0
 public static string GetOutAttributeName(AstOperand attr, ShaderStage stage)
 {
     return(GetAttributeName(attr, stage, isOutAttr: true));
 }
 public BlockFieldDescriptor(string tag, string referenceName, string displayName, string define, IControl control, ShaderStage shaderStage, bool isHidden = false, bool isUnknown = false)
     : base(tag, referenceName, define)
 {
     this.displayName = displayName;
     this.control     = control;
     this.shaderStage = shaderStage;
     this.isHidden    = isHidden;
     this.isUnknown   = isUnknown;
 }
Пример #32
0
        public static string GetAttributeName(AstOperand attr, ShaderStage stage, bool isOutAttr = false, string indexExpr = "0")
        {
            int value = attr.Value;

            string swzMask = GetSwizzleMask((value >> 2) & 3);

            if (value >= AttributeConsts.UserAttributeBase &&
                value < AttributeConsts.UserAttributeEnd)
            {
                value -= AttributeConsts.UserAttributeBase;

                string prefix = isOutAttr
                    ? DefaultNames.OAttributePrefix
                    : DefaultNames.IAttributePrefix;

                string name = $"{prefix}{(value >> 4)}";

                if (stage == ShaderStage.Geometry && !isOutAttr)
                {
                    name += $"[{indexExpr}]";
                }

                name += "." + swzMask;

                return(name);
            }
            else
            {
                if (value >= AttributeConsts.FragmentOutputColorBase &&
                    value < AttributeConsts.FragmentOutputColorEnd)
                {
                    value -= AttributeConsts.FragmentOutputColorBase;

                    return($"{DefaultNames.OAttributePrefix}{(value >> 4)}.{swzMask}");
                }
                else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr))
                {
                    // TODO: There must be a better way to handle this...
                    if (stage == ShaderStage.Fragment)
                    {
                        switch (value & ~3)
                        {
                        case AttributeConsts.PositionX: return("gl_FragCoord.x");

                        case AttributeConsts.PositionY: return("gl_FragCoord.y");

                        case AttributeConsts.PositionZ: return("gl_FragCoord.z");

                        case AttributeConsts.PositionW: return("1.0");
                        }
                    }

                    string name = builtInAttr.Name;

                    if (stage == ShaderStage.Geometry && !isOutAttr)
                    {
                        name = $"gl_in[{indexExpr}].{name}";
                    }

                    return(name);
                }
            }

            // TODO: Warn about unknown built-in attribute.

            return(isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0");
        }
Пример #33
0
        /// <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;

                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;
                    var uniformName = GL.GetActiveUniform(resourceId, activeUniformIndex, out uniformCount, out uniformType);
                    //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:
#endif
                    case ActiveUniformType.Sampler2D:
                    case ActiveUniformType.Sampler3D:     // TODO: remove Texture3D that is not available in OpenGL ES 2
                    case ActiveUniformType.SamplerCube:
#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);
        }
Пример #34
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)
        {
            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)
                {
                    // 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);

                    // 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();

                    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, ElementType = x.ElementType.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 <Stride.Core.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                            if (layoutQualifier == null)
                            {
                                layoutQualifier            = new Stride.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 <Stride.Core.Shaders.Ast.Glsl.LayoutQualifier>().FirstOrDefault();
                            if (layoutQualifier == null)
                            {
                                layoutQualifier      = new Stride.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);
        }
Пример #35
0
 public Shader CreateShaderFromFile(ShaderStage shaderStage, string filePath, VertexType vertexType, IEnumerable <(string, string)> macros)
Пример #36
0
        private static void MarkResourceBindingAsUsed(EffectReflection reflection, int resourceBindingIndex, ShaderStage stage)
        {
            var resourceBinding = reflection.ResourceBindings[resourceBindingIndex];

            if (resourceBinding.Stage == ShaderStage.None)
            {
                resourceBinding.Stage = stage;
                reflection.ResourceBindings[resourceBindingIndex] = resourceBinding;
            }
        }
Пример #37
0
 VertexShader CreateNative(ShaderStage outputStage)
 {
     var text = GenerateText<CVertexShader, ShaderStage>(outputStage, WriteLayout, WriteIOAndCode);
     VertexShader glShader;
     string errors;
     if (!VertexShader.TryCompile(text, out glShader, out errors))
         throw new Exception("Failed to compile a shader.\r\n\r\nShader Text:\r\n\r\n" + text + "\r\n\r\nErrors:\r\n\r\n" + errors);
     return glShader;
 }
Пример #38
0
        /// <summary>
        /// Converts the hlsl code into glsl and stores the result as plain text
        /// </summary>
        /// <param name="shaderSource">the hlsl shader</param>
        /// <param name="entryPoint">the entrypoint function name</param>
        /// <param name="stage">the shader pipeline stage</param>
        /// <param name="effectParameters"></param>
        /// <param name="reflection">the reflection gathered from the hlsl analysis</param>
        /// <param name="sourceFilename">the name of the source file</param>
        /// <returns></returns>
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, EffectCompilerParameters effectParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var shaderBytecodeResult = new ShaderBytecodeResult();

            byte[] rawData;

            var inputAttributeNames = new Dictionary <int, string>();
            var resourceBindings    = new Dictionary <string, int>();

            GlslShaderPlatform shaderPlatform;
            int shaderVersion;

            switch (effectParameters.Platform)
            {
            case GraphicsPlatform.OpenGL:
                shaderPlatform = GlslShaderPlatform.OpenGL;
                shaderVersion  = 410;
                break;

            case GraphicsPlatform.OpenGLES:
                shaderPlatform = GlslShaderPlatform.OpenGLES;
                shaderVersion  = 300;
                break;

            case GraphicsPlatform.Vulkan:
                shaderPlatform = GlslShaderPlatform.Vulkan;
                shaderVersion  = 450;
                break;

            default:
                throw new ArgumentOutOfRangeException("effectParameters.Platform");
            }

            var shader = Compile(shaderSource, entryPoint, stage, shaderPlatform, shaderVersion, shaderBytecodeResult, reflection, inputAttributeNames, resourceBindings, sourceFilename);

            if (shader == null)
            {
                return(shaderBytecodeResult);
            }

            if (effectParameters.Platform == GraphicsPlatform.OpenGLES)      // TODO: Add check to run on android only. The current version breaks OpenGL ES on windows.
            {
                //TODO: Remove this ugly hack!
                if (shaderSource.Contains($"Texture2D StrideInternal_TextureExt0") && shader.Contains("uniform sampler2D"))
                {
                    if (shaderPlatform != GlslShaderPlatform.OpenGLES || shaderVersion != 300)
                    {
                        throw new Exception("Invalid GLES platform or version: require OpenGLES 300");
                    }

                    shader = shader.Replace("uniform sampler2D", "uniform samplerExternalOES");
                    shader = shader.Replace("#version 300 es", "#version 300 es\n#extension GL_OES_EGL_image_external_essl3 : require");
                }
            }

            if (effectParameters.Platform == GraphicsPlatform.Vulkan)
            {
                string inputFileExtension;
                switch (stage)
                {
                case ShaderStage.Vertex: inputFileExtension = ".vert"; break;

                case ShaderStage.Pixel: inputFileExtension = ".frag"; break;

                case ShaderStage.Geometry: inputFileExtension = ".geom"; break;

                case ShaderStage.Domain: inputFileExtension = ".tese"; break;

                case ShaderStage.Hull: inputFileExtension = ".tesc"; break;

                case ShaderStage.Compute: inputFileExtension = ".comp"; break;

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

                var inputFileName  = Path.ChangeExtension(Path.GetTempFileName(), inputFileExtension);
                var outputFileName = Path.ChangeExtension(inputFileName, ".spv");

                // Write shader source to disk
                File.WriteAllBytes(inputFileName, Encoding.ASCII.GetBytes(shader));

                // Run shader compiler
                string filename;
                switch (Platform.Type)
                {
                case PlatformType.Windows:
                case PlatformType.UWP:
                    filename = @"win-x64\glslangValidator.exe";
                    break;

                case PlatformType.Linux:
                    filename = @"linux-x64\glslangValidator.bin";
                    break;

                case PlatformType.macOS:
                    filename = @"osx-x64\glslangValidator.bin";
                    break;

                default:
                    throw new PlatformNotSupportedException();
                }
                ShellHelper.RunProcessAndRedirectToLogger(filename, $"-V -o {outputFileName} {inputFileName}", null, shaderBytecodeResult);

                if (!File.Exists(outputFileName))
                {
                    shaderBytecodeResult.Error("Failed to generate SPIR-V from GLSL");
                    return(shaderBytecodeResult);
                }

                // Read compiled shader
                var shaderBytecodes = new ShaderInputBytecode
                {
                    InputAttributeNames = inputAttributeNames,
                    ResourceBindings    = resourceBindings,
                    Data = File.ReadAllBytes(outputFileName),
                };

                using (var stream = new MemoryStream())
                {
                    BinarySerialization.Write(stream, shaderBytecodes);
                    rawData = stream.ToArray();
                }

                // Cleanup temp files
                File.Delete(inputFileName);
                File.Delete(outputFileName);
            }
            else
            {
                // store string on OpenGL platforms
                rawData = Encoding.UTF8.GetBytes(shader);
            }

            var bytecodeId = ObjectId.FromBytes(rawData);
            var bytecode   = new ShaderBytecode(bytecodeId, rawData);

            bytecode.Stage = stage;

            shaderBytecodeResult.Bytecode = bytecode;

            return(shaderBytecodeResult);
        }
Пример #39
0
 protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
 {
     m_Id               = slotId;
     m_DisplayName      = displayName;
     m_SlotType         = slotType;
     m_Priority         = priority;
     m_Hidden           = hidden;
     m_ShaderOutputName = shaderOutputName;
     this.shaderStage   = shaderStage;
 }
Пример #40
0
 internal ConstantBufferCollection(ShaderStage stage, int maxBuffers)
 {
     _stage   = stage;
     _buffers = new ConstantBuffer[maxBuffers];
     _valid   = 0;
 }
Пример #41
0
        public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
        {
            switch (type)
            {
            case SlotValueType.SamplerState:
                return(new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.DynamicMatrix:
                return(new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Matrix4:
                return(new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Matrix3:
                return(new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Matrix2:
                return(new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Texture2D:
                return(slotType == SlotType.Input
                        ? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
                        : new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Cubemap:
                return(slotType == SlotType.Input
                        ? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
                        : new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.Gradient:
                return(slotType == SlotType.Input
                        ? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
                        : new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden));

            case SlotValueType.DynamicVector:
                return(new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden));

            case SlotValueType.Vector4:
                return(new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden));

            case SlotValueType.Vector3:
                return(new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden));

            case SlotValueType.Vector2:
                return(new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden));

            case SlotValueType.Vector1:
                return(new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStage, hidden: hidden));

            case SlotValueType.Dynamic:
                return(new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStage, hidden));

            case SlotValueType.Boolean:
                return(new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStage, hidden));
            }

            throw new ArgumentOutOfRangeException("type", type, null);
        }
Пример #42
0
 public ShaderGeneratorResult GenerateSharedVertexShader(VertexType vertexType, ShaderStage entryPoint)
 {
     return(null);
 }
Пример #43
0
 private void PlatformConstruct(ShaderStage stage, byte[] shaderBytecode)
 {
     GlslCode = System.Text.Encoding.ASCII.GetString(shaderBytecode);
     HashKey  = HashHelper.ComputeHash(shaderBytecode);
 }
Пример #44
0
 public bool IsMethodSharedInEntryPoint(ShaderStage entryPoint, int method_index)
 {
     return(method_index == 1);
 }
Пример #45
0
        public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, ShaderStage stage, EffectCompilerParameters effectParameters, EffectReflection reflection, string sourceFilename = null)
        {
            var isDebug    = effectParameters.Debug;
            var optimLevel = effectParameters.OptimizationLevel;
            var profile    = effectParameters.Profile;

            var shaderModel = ShaderStageToString(stage) + "_" + ShaderProfileFromGraphicsProfile(profile);

            var shaderFlags = ShaderFlags.None;

            if (isDebug)
            {
                shaderFlags = ShaderFlags.Debug;
            }
            switch (optimLevel)
            {
            case 0:
                shaderFlags |= ShaderFlags.OptimizationLevel0;
                break;

            case 1:
                shaderFlags |= ShaderFlags.OptimizationLevel1;
                break;

            case 2:
                shaderFlags |= ShaderFlags.OptimizationLevel2;
                break;

            case 3:
                shaderFlags |= ShaderFlags.OptimizationLevel3;
                break;
            }
            SharpDX.Configuration.ThrowOnShaderCompileError = false;

            // Compile using D3DCompiler
            var compilationResult = SharpDX.D3DCompiler.ShaderBytecode.Compile(shaderSource, entryPoint, shaderModel, shaderFlags, EffectFlags.None, null, null, sourceFilename);

            var byteCodeResult = new ShaderBytecodeResult();

            if (compilationResult.HasErrors || compilationResult.Bytecode == null)
            {
                // Log compilation errors
                byteCodeResult.Error(compilationResult.Message);
            }
            else
            {
                // TODO: Make this optional
                try
                {
                    byteCodeResult.DisassembleText = compilationResult.Bytecode.Disassemble();
                }
                catch (SharpDXException)
                {
                }

                // As effect bytecode binary can changed when having debug infos (with d3dcompiler_47), we are calculating a bytecodeId on the stripped version
                var rawData    = compilationResult.Bytecode.Strip(StripFlags.CompilerStripDebugInformation | StripFlags.CompilerStripReflectionData);
                var bytecodeId = ObjectId.FromBytes(rawData);
                byteCodeResult.Bytecode = new ShaderBytecode(bytecodeId, compilationResult.Bytecode.Data)
                {
                    Stage = stage
                };

                // If compilation succeed, then we can update reflection.
                UpdateReflection(byteCodeResult.Bytecode, reflection, byteCodeResult);

                if (!string.IsNullOrEmpty(compilationResult.Message))
                {
                    byteCodeResult.Warning(compilationResult.Message);
                }
            }

            return(byteCodeResult);
        }
Пример #46
0
 private static string ShaderStageToString(ShaderStage stage)
 {
     string shaderStageText;
     switch (stage)
     {
         case ShaderStage.Compute:
             shaderStageText = "cs";
             break;
         case ShaderStage.Vertex:
             shaderStageText = "vs";
             break;
         case ShaderStage.Hull:
             shaderStageText = "hs";
             break;
         case ShaderStage.Domain:
             shaderStageText = "ds";
             break;
         case ShaderStage.Geometry:
             shaderStageText = "gs";
             break;
         case ShaderStage.Pixel:
             shaderStageText = "ps";
             break;
         default:
             throw new ArgumentException("Stage not supported", "stage");
     }
     return shaderStageText;
 }
Пример #47
0
        /// <summary>
        ///     Sets a sampler state to the shader pipeline.
        /// </summary>
        /// <param name="stage">The shader stage.</param>
        /// <param name="slot">The binding slot.</param>
        /// <param name="samplerState">The sampler state to set.</param>
        internal void SetSamplerState(ShaderStage stage, int slot, SamplerState samplerState)
        {
            if (stage == ShaderStage.None)
                throw new ArgumentException("Cannot use Stage.None", "stage");
            int stageIndex = (int)stage - 1;

            int slotIndex = stageIndex * SamplerStateCount + slot;
            if (samplerStates[slotIndex] != samplerState)
            {
                samplerStates[slotIndex] = samplerState;
                shaderStages[stageIndex].SetSampler(slot, samplerState != null ? (SharpDX.Direct3D11.SamplerState)samplerState.NativeDeviceChild : null);
            }
        }
Пример #48
0
        /// <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 SILICONSTUDIO_XENKO_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 [{0}]", constantBufferName);
                    return;
                }
                var constantBufferIndex = effectReflection.ResourceBindings.FindIndex(x => x.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(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 SILICONSTUDIO_XENKO_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 [{0}] in constant buffer [{1}]", variableIndexGroup.Name, 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 !SILICONSTUDIO_XENKO_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 !SILICONSTUDIO_XENKO_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

#if SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES
                    // Process uniforms
                    if (GraphicsDevice.IsOpenGLES2)
                    {
                        switch (uniformType)
                        {
                            case ActiveUniformType.Bool:
                            case ActiveUniformType.Int:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(int)*1, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.BoolVec2:
                            case ActiveUniformType.IntVec2:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(int)*2, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.BoolVec3:
                            case ActiveUniformType.IntVec3:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(int)*3, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.BoolVec4:
                            case ActiveUniformType.IntVec4:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(int)*4, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.Float:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(float)*1, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.FloatVec2:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(float)*2, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.FloatVec3:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(float)*3, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.FloatVec4:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(float)*4, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.FloatMat4:
                                AddUniform(effectReflection, validConstantBuffers, sizeof(float)*4*4, uniformCount, uniformName, uniformType);
                                break;
                            case ActiveUniformType.FloatMat2:
                            case ActiveUniformType.FloatMat3:
                                throw new NotImplementedException();
                        }
                    }
#endif

                    switch (uniformType)
                    {
#if !SILICONSTUDIO_XENKO_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 [{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.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);
        }
Пример #49
0
        /// <summary>
        ///     Sets an unordered access view to the shader pipeline.
        /// </summary>
        /// <param name="stage">The stage.</param>
        /// <param name="slot">The slot.</param>
        /// <param name="unorderedAccessView">The unordered access view.</param>
        /// <exception cref="System.ArgumentException">Invalid stage.;stage</exception>
        internal void SetUnorderedAccessView(ShaderStage stage, int slot, GraphicsResource unorderedAccessView)
        {
            if (stage != ShaderStage.Compute)
                throw new ArgumentException("Invalid stage.", "stage");

            NativeDeviceContext.ComputeShader.SetUnorderedAccessView(slot, unorderedAccessView != null ? unorderedAccessView.NativeUnorderedAccessView : null);
        }
Пример #50
0
 public void SetStorageBuffer(int index, ShaderStage stage, BufferRange buffer)
 {
     SetBuffer(index, stage, buffer, isStorage: true);
 }
Пример #51
0
 public static bool HasFlag(ShaderStage option, ShaderStage flag)
 {
     return((option & flag) != 0);
 }
Пример #52
0
        /// <summary>
        /// Translates the binary Maxwell shader code to something that the host API accepts.
        /// </summary>
        /// <remarks>
        /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader.
        /// </remarks>
        /// <param name="state">Current GPU state</param>
        /// <param name="flags">Flags that controls shader translation</param>
        /// <param name="stage">Shader stage</param>
        /// <param name="gpuVa">GPU virtual address of the shader code</param>
        /// <param name="gpuVaA">Optional GPU virtual address of the "Vertex A" shader code</param>
        /// <returns>Compiled graphics shader code</returns>
        private ShaderCodeHolder TranslateGraphicsShader(GpuState state, TranslationFlags flags, ShaderStage stage, ulong gpuVa, ulong gpuVaA = 0)
        {
            if (gpuVa == 0)
            {
                return(null);
            }

            GpuAccessor gpuAccessor = new GpuAccessor(_context, state, (int)stage - 1);

            if (gpuVaA != 0)
            {
                ShaderProgram program = Translator.Translate(gpuVaA, gpuVa, gpuAccessor, flags);

                byte[] codeA = _context.MemoryManager.GetSpan(gpuVaA, program.SizeA).ToArray();
                byte[] codeB = _context.MemoryManager.GetSpan(gpuVa, program.Size).ToArray();

                _dumper.Dump(codeA, compute: false, out string fullPathA, out string codePathA);
                _dumper.Dump(codeB, compute: false, out string fullPathB, out string codePathB);

                if (fullPathA != null && fullPathB != null && codePathA != null && codePathB != null)
                {
                    program.Prepend("// " + codePathB);
                    program.Prepend("// " + fullPathB);
                    program.Prepend("// " + codePathA);
                    program.Prepend("// " + fullPathA);
                }

                return(new ShaderCodeHolder(program, codeB, codeA));
            }
            else
            {
                ShaderProgram program = Translator.Translate(gpuVa, gpuAccessor, flags);

                byte[] code = _context.MemoryManager.GetSpan(gpuVa, program.Size).ToArray();

                _dumper.Dump(code, compute: false, out string fullPath, out string codePath);

                if (fullPath != null && codePath != null)
                {
                    program.Prepend("// " + codePath);
                    program.Prepend("// " + fullPath);
                }

                return(new ShaderCodeHolder(program, code));
            }
        }
Пример #53
0
        /// <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;

                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;
                    var uniformName = GL.GetActiveUniform(resourceId, activeUniformIndex, out uniformCount, out uniformType);
                    //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:
#endif
                        case ActiveUniformType.Sampler2D:
                        case ActiveUniformType.Sampler3D: // TODO: remove Texture3D that is not available in OpenGL ES 2
                        case ActiveUniformType.SamplerCube:
#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);
        }
 /// <summary>
 /// Sets an unordered access view to the shader pipeline.
 /// </summary>
 /// <param name="stage">The stage.</param>
 /// <param name="slot">The slot.</param>
 /// <param name="unorderedAccessView">The unordered access view.</param>
 /// <exception cref="System.ArgumentException">Invalid stage.;stage</exception>
 public void SetUnorderedAccessView(ShaderStage stage, int slot, GraphicsResource unorderedAccessView)
 {
     throw new NotImplementedException();
 }
Пример #55
0
 public bool IsSharedPixelShaderUsingMethods(ShaderStage entryPoint)
 {
     return(entryPoint == ShaderStage.Shadow_Generate);
 }
Пример #56
0
 public void SetUniformBuffer(int index, ShaderStage stage, BufferRange buffer)
 {
     SetBuffer(index, stage, buffer, isStorage: false);
 }
 internal ConstantBufferCollection(ShaderStage stage, int maxBuffers)
 {
     _stage = stage;
     _buffers = new ConstantBuffer[maxBuffers];
     _valid = 0;
 }
Пример #58
0
 public bool IsSharedPixelShaderWithoutMethod(ShaderStage entryPoint)
 {
     return(false);
 }
Пример #59
0
 public static Shader New(GraphicsDevice device, ShaderStage shaderStage, byte[] shaderBytecode)
 {
     return new Shader(device, shaderStage, shaderBytecode);
 }
Пример #60
0
 public bool IsVertexShaderShared(ShaderStage entryPoint)
 {
     return(true);
 }