public InputLayout GetInputLayout(EffectInputSignature effectInputSignature, VertexArrayLayout vertexArrayLayout)
        {
            var inputKey = new InputKey(effectInputSignature, vertexArrayLayout);

            InputLayout inputLayout;

            // TODO: Check if it is really worth to use ConcurrentDictionary
            lock (registeredSignatures)
            {
                if (!registeredSignatures.TryGetValue(inputKey, out inputLayout))
                {
                    try
                    {
                        inputLayout = new InputLayout(graphicsDevice.NativeDevice, effectInputSignature.NativeSignature, vertexArrayLayout.InputElements);
                    }
                    catch (Exception)
                    {
                        throw new InvalidOperationException("The provided vertex array input elements are not matching the ones of the shader." +
                                                            " [Details: EffectInputSignature='{0}', VertexArrayLayout='{1}]".ToFormat(effectInputSignature.ToString(), vertexArrayLayout.ToString()));
                    }
                    registeredSignatures.Add(inputKey, inputLayout);
                }

                ((IUnknown)inputLayout).AddReference();
            }
            return(inputLayout);
        }
        public static VertexArrayObject New(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, params VertexBufferBinding[] vertexBufferBindings)
        {
            // Store SamplerState in a cache (D3D seems to have quite bad concurrency when using CreateSampler while rendering)
            VertexArrayObject vertexArrayObject;
            var description = new Description(shaderSignature, vertexBufferBindings, indexBufferBinding);

            lock (graphicsDevice.CachedVertexArrayObjects)
            {
                if (graphicsDevice.CachedVertexArrayObjects.TryGetValue(description, out vertexArrayObject))
                {
                    // TODO: Appropriate destroy
                    vertexArrayObject.AddReferenceInternal();
                }
                else
                {
                    vertexArrayObject = new VertexArrayObject(graphicsDevice, shaderSignature, indexBufferBinding, vertexBufferBindings);

                    // For now store description as is to avoid having to recreate it on Destroy.
                    // It would probably save little bit of memory space to try to reuse existing fields and add only what's missing.
                    vertexArrayObject.description = description;

                    graphicsDevice.CachedVertexArrayObjects.Add(description, vertexArrayObject);
                }
            }

            return(vertexArrayObject);
        }
Exemple #3
0
        public VertexArrayObjectInstance(GraphicsDevice graphicsDevice, EffectInputSignature effectInputSignature, VertexAttrib[] sharedVertexAttribs, int indexBufferId)
        {
            this.graphicsDevice = graphicsDevice;
            this.indexBufferId  = indexBufferId;
            programAttributes   = effectInputSignature.Attributes;

            int vertexAttributeCount = 0;

            for (int i = 0; i < sharedVertexAttribs.Length; i++)
            {
                if (programAttributes.ContainsKey(sharedVertexAttribs[i].AttributeName))
                {
                    vertexAttributeCount++;
                }
            }

            vertexAttribs = new VertexAttrib[vertexAttributeCount];

            int j = 0;

            for (int i = 0; i < sharedVertexAttribs.Length; i++)
            {
                AddAttribute(ref j, ref sharedVertexAttribs[i], ref enabledVertexAttribArrays);
            }
        }
        private void ClearStateImpl()
        {
            NativeDeviceContext.ClearState();

            for (int i = 0; i < samplerStates.Length; ++i)
            {
                samplerStates[i] = null;
            }
            for (int i = 0; i < constantBuffers.Length; ++i)
            {
                constantBuffers[i] = null;
            }
            for (int i = 0; i < unorderedAccessViews.Length; ++i)
            {
                unorderedAccessViews[i] = null;
            }
            for (int i = 0; i < currentRenderTargetViews.Length; i++)
            {
                currentRenderTargetViews[i] = null;
            }

            currentEffectInputSignature = null;
            currentVertexArrayLayout    = null;
            currentInputLayout          = null;
            currentVertexArrayObject    = null;
            CurrentEffect = null;
        }
Exemple #5
0
        private void Initialize(ParameterCollection usedParameters)
        {
            program    = EffectProgram.New(graphicsDeviceDefault, bytecode);
            reflection = bytecode.Reflection;

            // prepare resource bindings used internally
            resourceBindings = new EffectParameterResourceBinding[bytecode.Reflection.ResourceBindings.Count];
            for (int i = 0; i < resourceBindings.Length; i++)
            {
                resourceBindings[i].Description = bytecode.Reflection.ResourceBindings[i];
            }
            defaultParameters = new ParameterCollection();
            inputSignature    = program.InputSignature;
            LoadDefaultParameters();

            CompilationParameters        = new ParameterCollection();
            DefaultCompilationParameters = new ParameterCollection();
            if (usedParameters != null)
            {
                foreach (var parameter in usedParameters)
                {
                    if (parameter.Key != CompilerParameters.DebugKey && parameter.Key != CompilerParameters.GraphicsPlatformKey && parameter.Key != CompilerParameters.GraphicsProfileKey)
                    {
                        CompilationParameters.SetObject(parameter.Key, parameter.Value);
                    }
                }
            }

            foreach (var key in CompilationParameters.Keys)
            {
                DefaultCompilationParameters.RegisterParameter(key, false);
            }
        }
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings = vertexBufferBindings;
            this.indexBufferBinding = indexBufferBinding;
            this.preferredInputSignature = shaderSignature;

            CreateAttributes();
        }
Exemple #7
0
            public SharedData(GraphicsDevice device, EffectInputSignature defaultSignature)
            {
                var vertexBuffer = Buffer.Vertex.New(device, QuadsVertices).DisposeBy(this);

                // Register reload
                vertexBuffer.Reload = (graphicsResource) => ((Buffer)graphicsResource).Recreate(QuadsVertices);

                VertexBuffer = VertexArrayObject.New(device, defaultSignature, new VertexBufferBinding(vertexBuffer, VertexPositionTexture.Layout, QuadsVertices.Length, VertexPositionTexture.Size)).DisposeBy(this);
            }
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings    = vertexBufferBindings;
            this.indexBufferBinding      = indexBufferBinding;
            this.preferredInputSignature = shaderSignature;

            CreateAttributes();
        }
            public Description(EffectInputSignature shaderSignature, VertexBufferBinding[] vertexBuffers, IndexBufferBinding indexBuffer)
            {
                ShaderSignature = shaderSignature;
                VertexBuffers   = vertexBuffers ?? emptyVertexBufferBindings;
                IndexBuffer     = indexBuffer;

                // Precompute hash code
                hashCode = 0;
                hashCode = ComputeHashCode();
            }
        private void CreateShaders()
        {
            foreach (var shaderBytecode in effectBytecode.Stages)
            {
                var bytecodeRaw = shaderBytecode.Data;
                var reflection = effectBytecode.Reflection;

                // TODO CACHE Shaders with a bytecode hash
                switch (shaderBytecode.Stage)
                {
                    case ShaderStage.Vertex:
                        vertexShader = new VertexShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        // Note: input signature can be reused when reseting device since it only stores non-GPU data,
                        // so just keep it if it has already been created before.
                        if (inputSignature == null)
                            inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shaderBytecode.Id, bytecodeRaw));
                        break;
                    case ShaderStage.Domain:
                        domainShader = new DomainShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        break;
                    case ShaderStage.Hull:
                        hullShader = new HullShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        break;
                    case ShaderStage.Geometry:
                        if (reflection.ShaderStreamOutputDeclarations != null && reflection.ShaderStreamOutputDeclarations.Count > 0)
                        {
                            // Calculate the strides
                            var soStrides = new List<int>();
                            foreach (var streamOutputElement in reflection.ShaderStreamOutputDeclarations)
                            {
                                for (int i = soStrides.Count; i < (streamOutputElement.Stream + 1); i++)
                                {
                                    soStrides.Add(0);
                                }

                                soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float);
                            }
                            var soElements = new StreamOutputElement[0]; // TODO CREATE StreamOutputElement from bytecode.Reflection.ShaderStreamOutputDeclarations
                            geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw, soElements, soStrides.ToArray(), reflection.StreamOutputRasterizedStream);
                        }
                        else
                        {
                            geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        }
                        break;
                    case ShaderStage.Pixel:
                        pixelShader = new PixelShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        break;
                    case ShaderStage.Compute:
                        computeShader = new ComputeShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                        break;
                }
            }
        }
        private VertexArrayObjectInstance GetInstance(EffectInputSignature effectInputSignature)
        {
            VertexArrayObjectInstance inputLayout;

            lock (registeredInstances)
            {
                if (!registeredInstances.TryGetValue(effectInputSignature, out inputLayout))
                {
                    inputLayout = new VertexArrayObjectInstance(GraphicsDevice, effectInputSignature, vertexAttribs, indexBufferId);
                    registeredInstances.Add(effectInputSignature, inputLayout);
                }
            }
            return(inputLayout);
        }
        /// <summary>
        /// Gets the original create signature.
        /// </summary>
        /// <param name="signature">The signature.</param>
        /// <returns>VertexArrayLayout.</returns>
        internal static EffectInputSignature GetOrCreateLayout(EffectInputSignature signature)
        {
            EffectInputSignature registeredLayout;

            lock (RegisteredSignatures)
            {
                if (!RegisteredSignatures.TryGetValue(signature.Id, out registeredLayout))
                {
                    RegisteredSignatures.Add(signature.Id, signature);
                    registeredLayout = signature;
                }
            }
            return(registeredLayout);
        }
Exemple #13
0
        private void Initialize(ParameterCollection usedParameters)
        {
            program    = EffectProgram.New(graphicsDeviceDefault, bytecode);
            reflection = program.Reflection;

            // prepare resource bindings used internally
            resourceBindings = new EffectParameterResourceBinding[reflection.ResourceBindings.Count];
            for (int i = 0; i < resourceBindings.Length; i++)
            {
                resourceBindings[i].Description = reflection.ResourceBindings[i];
            }
            defaultParameters = new ParameterCollection();
            inputSignature    = program.InputSignature;
            LoadDefaultParameters();
        }
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings = vertexBufferBindings;
            this.indexBufferBinding = indexBufferBinding;
            this.preferredInputSignature = shaderSignature;
            
            // Increase the reference count on the provided buffers -> we do not want to take the ownership
            foreach (VertexBufferBinding vertexBufferBinding in vertexBufferBindings)
                vertexBufferBinding.Buffer.AddReferenceInternal();

            if (indexBufferBinding != null)
                indexBufferBinding.Buffer.AddReferenceInternal();

            CreateAttributes();
        }
        internal void Apply(EffectInputSignature effectInputSignature)
        {
            if (effectInputSignature == null)
            {
                throw new ArgumentNullException("effectInputSignature");
            }

            // Optimization: If the current VAO and shader signature was previously used, we can use it directly without asking for a proper instance
            if (RequiresApply(effectInputSignature))
            {
                currentInstance = ReferenceEquals(preferredInputSignature, effectInputSignature)
                    ? preferredInstance
                    : GetInstance(effectInputSignature);
                currentShaderSignature = effectInputSignature;
            }

            currentInstance.Apply(GraphicsDevice);
        }
        private void ReleaseDevice()
        {
            // Display D3D11 ref counting info
            ClearState();
            NativeDevice.ImmediateContext.Flush();
            NativeDevice.ImmediateContext.Dispose();

            if (IsDebugMode)
            {
                var deviceDebug = new DeviceDebug(NativeDevice);
                deviceDebug.ReportLiveDeviceObjects(ReportingLevel.Detail);
            }

            currentInputLayout          = null;
            currentEffectInputSignature = null;
            currentVertexArrayObject    = null;
            currentVertexArrayLayout    = null;
            nativeDevice.Dispose();
        }
Exemple #17
0
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings = vertexBufferBindings;
            this.indexBufferBinding   = indexBufferBinding;
            this.EffectInputSignature = shaderSignature;

            // Calculate Direct3D11 InputElement
            int inputElementCount = vertexBufferBindings.Sum(t => t.Declaration.VertexElements.Length);
            var inputElements     = new InputElement[inputElementCount];

            int j = 0;

            for (int i = 0; i < vertexBufferBindings.Length; i++)
            {
                var declaration = vertexBufferBindings[i].Declaration;
                vertexBufferBindings[i].Buffer.AddReferenceInternal();
                foreach (var vertexElementWithOffset in declaration.EnumerateWithOffsets())
                {
                    var vertexElement = vertexElementWithOffset.VertexElement;
                    inputElements[j++] = new InputElement
                    {
                        Slot              = i,
                        SemanticName      = vertexElement.SemanticName,
                        SemanticIndex     = vertexElement.SemanticIndex,
                        AlignedByteOffset = vertexElementWithOffset.Offset,
                        Format            = (SharpDX.DXGI.Format)vertexElement.Format,
                    };
                }
            }

            Layout = VertexArrayLayout.GetOrCreateLayout(new VertexArrayLayout(inputElements));

            if (indexBufferBinding != null)
            {
                indexBufferBinding.Buffer.AddReferenceInternal();
                indexBufferOffset = indexBufferBinding.Offset;
                indexFormat       = (indexBufferBinding.Is32Bit ? SharpDX.DXGI.Format.R32_UInt : SharpDX.DXGI.Format.R16_UInt);
            }

            CreateResources();
        }
Exemple #18
0
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings    = vertexBufferBindings;
            this.indexBufferBinding      = indexBufferBinding;
            this.preferredInputSignature = shaderSignature;

            // Increase the reference count on the provided buffers -> we do not want to take the ownership
            foreach (VertexBufferBinding vertexBufferBinding in vertexBufferBindings)
            {
                vertexBufferBinding.Buffer.AddReferenceInternal();
            }

            if (indexBufferBinding != null)
            {
                indexBufferBinding.Buffer.AddReferenceInternal();
            }

            CreateAttributes();
        }
        private VertexArrayObject(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, IndexBufferBinding indexBufferBinding, VertexBufferBinding[] vertexBufferBindings)
            : base(graphicsDevice)
        {
            this.vertexBufferBindings = vertexBufferBindings;
            this.indexBufferBinding = indexBufferBinding;
            this.EffectInputSignature = shaderSignature;

            // Calculate Direct3D11 InputElement
            int inputElementCount = vertexBufferBindings.Sum(t => t.Declaration.VertexElements.Length);
            var inputElements = new InputElement[inputElementCount];

            int j = 0;
            for (int i = 0; i < vertexBufferBindings.Length; i++)
            {
                var declaration = vertexBufferBindings[i].Declaration;
                vertexBufferBindings[i].Buffer.AddReferenceInternal();
                foreach (var vertexElementWithOffset in declaration.EnumerateWithOffsets())
                {
                    var vertexElement = vertexElementWithOffset.VertexElement;
                    inputElements[j++] = new InputElement
                        {
                            Slot = i,
                            SemanticName = vertexElement.SemanticName,
                            SemanticIndex = vertexElement.SemanticIndex,
                            AlignedByteOffset = vertexElementWithOffset.Offset,
                            Format = (SharpDX.DXGI.Format)vertexElement.Format,
                        };
                }
            }

            Layout = VertexArrayLayout.GetOrCreateLayout(new VertexArrayLayout(inputElements));

            if (indexBufferBinding != null)
            {
                indexBufferBinding.Buffer.AddReferenceInternal();
                indexBufferOffset = indexBufferBinding.Offset;
                indexFormat = (indexBufferBinding.Is32Bit ? SharpDX.DXGI.Format.R32_UInt : SharpDX.DXGI.Format.R16_UInt);
            }

            CreateResources();
        }
        public VertexArrayObjectInstance(GraphicsDevice graphicsDevice, EffectInputSignature effectInputSignature, VertexAttrib[] sharedVertexAttribs, int indexBufferId)
        {
            this.graphicsDevice = graphicsDevice;
            this.indexBufferId = indexBufferId;
            programAttributes = effectInputSignature.Attributes;

            int vertexAttributeCount = 0;
            for (int i = 0; i < sharedVertexAttribs.Length; i++)
            {
                if (programAttributes.ContainsKey(sharedVertexAttribs[i].AttributeName))
                {
                    vertexAttributeCount++;
                }
            }

            vertexAttribs = new VertexAttrib[vertexAttributeCount];

            int j = 0;
            for (int i = 0; i < sharedVertexAttribs.Length; i++)
            {
                AddAttribute(ref j, ref sharedVertexAttribs[i], ref enabledVertexAttribArrays);
            }
        }
        private void CreateShaders()
        {
            using (GraphicsDevice.UseOpenGLCreationContext())
            {
                resourceId = GL.CreateProgram();

                // Attach shaders
                foreach (var shader in effectBytecode.Stages)
                {
                    ShaderType shaderStage;
                    switch (shader.Stage)
                    {
                    case ShaderStage.Vertex:
                        shaderStage = ShaderType.VertexShader;
                        // We can't use VS only, since various attributes might get optimized when linked with a specific PS
                        // Maybe we should unify signature after checking attributes
                        //inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shader.Id, shader.Data));
                        inputSignature = new EffectInputSignature(shader.Id, shader.Data);
                        break;

                    case ShaderStage.Pixel:
                        shaderStage = ShaderType.FragmentShader;
                        break;

                    default:
                        throw new Exception("Unsupported shader stage");
                        break;
                    }

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    var shaderSources = BinarySerialization.Read <ShaderLevelBytecode>(shader.Data);
                    var shaderSource  = GraphicsDevice.IsOpenGLES2 ? shaderSources.DataES2 : shaderSources.DataES3;
#else
                    var shaderSource = shader.GetDataAsString();
#endif
                    var shaderId = GL.CreateShader(shaderStage);
                    GL.ShaderSource(shaderId, shaderSource);
                    GL.CompileShader(shaderId);

                    int compileStatus;
                    GL.GetShader(shaderId, ShaderParameter.CompileStatus, out compileStatus);
                    if (compileStatus != 1)
                    {
                        var glErrorMessage = GL.GetShaderInfoLog(shaderId);
                        throw new InvalidOperationException("Error while compiling GLSL shader. [{0}]".ToFormat(glErrorMessage));
                    }

                    GL.AttachShader(resourceId, shaderId);
                }

#if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                // Mark program as retrievable (necessary for later GL.GetProgramBinary).
                GL.ProgramParameter(resourceId, AssemblyProgramParameterArb.ProgramBinaryRetrievableHint, 1);
#endif

                // Link OpenGL program
                GL.LinkProgram(resourceId);

                // Check link results
                int linkStatus;
                GL.GetProgram(resourceId, ProgramParameter.LinkStatus, out linkStatus);
                if (linkStatus != 1)
                {
                    var infoLog = GL.GetProgramInfoLog(resourceId);
                    throw new InvalidOperationException("Error while linking GLSL shaders.\n" + infoLog);
                }

                if (inputSignature.Attributes.Count == 0) // the shader wasn't analyzed yet
                {
                    // Build attributes list for shader signature
                    int activeAttribCount;
                    GL.GetProgram(resourceId, ProgramParameter.ActiveAttributes, out activeAttribCount);

                    for (int activeAttribIndex = 0; activeAttribIndex < activeAttribCount; ++activeAttribIndex)
                    {
                        int size;
                        ActiveAttribType type;
                        var attribName = GL.GetActiveAttrib(resourceId, activeAttribIndex, out size, out type);
#if SILICONSTUDIO_PLATFORM_ANDROID
                        var attribIndex = GL.GetAttribLocation(resourceId, new StringBuilder(attribName));
#else
                        var attribIndex = GL.GetAttribLocation(resourceId, attribName);
#endif
                        inputSignature.Attributes.Add(attribName, attribIndex);
                    }
                }

                CreateReflection(effectBytecode.Reflection, effectBytecode.Stages[0].Stage); // need to regenerate the Uniforms on OpenGL ES

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                // Allocate a buffer that can cache all the bound parameters
                BoundUniforms = new byte[effectBytecode.Reflection.ConstantBuffers[0].Size];
#endif
            }

            // output the gathered errors
            foreach (var message in reflectionResult.Messages)
            {
                Console.WriteLine(message);
            }
            if (reflectionResult.HasErrors)
            {
                throw new Exception("Exception");
            }
        }
        private void CreateShaders()
        {
            using (GraphicsDevice.UseOpenGLCreationContext())
            {
                resourceId = GL.CreateProgram();

                // Attach shaders
                foreach (var shader in effectBytecode.Stages)
                {
                    ShaderType shaderStage;
                    switch (shader.Stage)
                    {
                        case ShaderStage.Vertex:
                            shaderStage = ShaderType.VertexShader;
                            // We can't use VS only, since various attributes might get optimized when linked with a specific PS
                            // Maybe we should unify signature after checking attributes
                            //inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shader.Id, shader.Data));
                            inputSignature = new EffectInputSignature(shader.Id, shader.Data);
                            break;
                        case ShaderStage.Pixel:
                            shaderStage = ShaderType.FragmentShader;
                            break;
                        default:
                            throw new Exception("Unsupported shader stage");
                            break;
                    }

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    var shaderSources = BinarySerialization.Read<ShaderLevelBytecode>(shader.Data);
                    var shaderSource = GraphicsDevice.IsOpenGLES2 ? shaderSources.DataES2 : shaderSources.DataES3;
#else
                    var shaderSource = shader.GetDataAsString();
#endif
                    var shaderId = GL.CreateShader(shaderStage);
                    GL.ShaderSource(shaderId, shaderSource);
                    GL.CompileShader(shaderId);

                    int compileStatus;
                    GL.GetShader(shaderId, ShaderParameter.CompileStatus, out compileStatus);
                    if (compileStatus != 1)
                    {
                        var glErrorMessage = GL.GetShaderInfoLog(shaderId);
                        throw new InvalidOperationException("Error while compiling GLSL shader. [{0}]".ToFormat(glErrorMessage));
                    }

                    GL.AttachShader(resourceId, shaderId);
                }

#if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                // Mark program as retrievable (necessary for later GL.GetProgramBinary).
                GL.ProgramParameter(resourceId, AssemblyProgramParameterArb.ProgramBinaryRetrievableHint, 1);
#endif

                // Link OpenGL program
                GL.LinkProgram(resourceId);

                // Check link results
                int linkStatus;
                GL.GetProgram(resourceId, ProgramParameter.LinkStatus, out linkStatus);
                if (linkStatus != 1)
                {
                    var infoLog = GL.GetProgramInfoLog(resourceId);
                    throw new InvalidOperationException("Error while linking GLSL shaders.\n" + infoLog);
                }

                if (inputSignature.Attributes.Count == 0) // the shader wasn't analyzed yet
                {
                    // Build attributes list for shader signature
                    int activeAttribCount;
                    GL.GetProgram(resourceId, ProgramParameter.ActiveAttributes, out activeAttribCount);

                    for (int activeAttribIndex = 0; activeAttribIndex < activeAttribCount; ++activeAttribIndex)
                    {
                        int size;
                        ActiveAttribType type;
                        var attribName = GL.GetActiveAttrib(resourceId, activeAttribIndex, out size, out type);
#if SILICONSTUDIO_PLATFORM_ANDROID
                        var attribIndex = GL.GetAttribLocation(resourceId, new StringBuilder(attribName));
#else
                        var attribIndex = GL.GetAttribLocation(resourceId, attribName);
#endif
                        inputSignature.Attributes.Add(attribName, attribIndex);
                    }
                }

                CreateReflection(effectBytecode.Reflection, effectBytecode.Stages[0].Stage); // need to regenerate the Uniforms on OpenGL ES

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                // Allocate a buffer that can cache all the bound parameters
                BoundUniforms = new byte[effectBytecode.Reflection.ConstantBuffers[0].Size];
#endif
            }

            // output the gathered errors
            foreach (var message in reflectionResult.Messages)
                Console.WriteLine(message);
            if (reflectionResult.HasErrors)
                throw new Exception("Exception");
        }
        private void ClearStateImpl()
        {
            NativeDeviceContext.ClearState();

            for (int i = 0; i < samplerStates.Length; ++i)
                samplerStates[i] = null;
            for (int i = 0; i < constantBuffers.Length; ++i)
                constantBuffers[i] = null;
            for (int i = 0; i < unorderedAccessViews.Length; ++i)
                unorderedAccessViews[i] = null;
            for (int i = 0; i < currentRenderTargetViews.Length; i++)
                currentRenderTargetViews[i] = null;

            currentEffectInputSignature = null;
            currentVertexArrayLayout = null;
            currentInputLayout = null;
            currentVertexArrayObject = null;
            CurrentEffect = null;
        }
        private void ReleaseDevice()
        {
            // Display D3D11 ref counting info
            ClearState();
            NativeDevice.ImmediateContext.Flush();
            NativeDevice.ImmediateContext.Dispose();

            if (IsDebugMode)
            {
                var deviceDebug = new DeviceDebug(NativeDevice);
                deviceDebug.ReportLiveDeviceObjects(ReportingLevel.Detail);
            }

            currentInputLayout = null;
            currentEffectInputSignature = null;
            currentVertexArrayObject = null;
            currentVertexArrayLayout = null;
            nativeDevice.Dispose();
        }
        private void CreateAttributes()
        {
            int vertexAttribCount = 0;

            for (int i = 0; i < vertexBufferBindings.Length; ++i)
            {
                vertexAttribCount += vertexBufferBindings[i].Declaration.VertexElements.Length;
            }

            vertexAttribs = new VertexAttrib[vertexAttribCount];
            int j = 0;

            for (int i = 0; i < vertexBufferBindings.Length; ++i)
            {
                var inputSlot    = vertexBufferBindings[i];
                var vertexBuffer = vertexBufferBindings[i].Buffer;

                foreach (var vertexElementAndOffset in inputSlot.Declaration.EnumerateWithOffsets())
                {
                    var vertexElement = vertexElementAndOffset.VertexElement;
                    var attributeName = "a_" + vertexElement.SemanticName + vertexElement.SemanticIndex;

                    var vertexElementFormat = ConvertVertexElementFormat(vertexElement.Format);
#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    IntPtr bufferStart = vertexBuffer.ResourceId == 0
                        ? vertexBuffer.StagingData
                        : (IntPtr)vertexBufferBindings[i].Offset;
#else
                    var bufferStart = (IntPtr)vertexBufferBindings[i].Offset;
#endif
                    vertexAttribs[j] = new VertexAttrib
                    {
                        VertexBufferId = vertexBuffer.ResourceId,
                        Index          = -1,
                        IsInteger      = IsInteger(vertexElementFormat.Type),
                        Size           = vertexElementFormat.Size,
                        Type           = vertexElementFormat.Type,
                        Normalized     = vertexElementFormat.Normalized,
                        Stride         = inputSlot.Declaration.VertexStride,
                        Offset         = bufferStart + vertexElementAndOffset.Offset,
                        AttributeName  = attributeName
                    };

                    j++;
                }
            }

            if (indexBufferBinding != null)
            {
                indexBufferId = indexBufferBinding.Buffer.resourceId;

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                if (GraphicsDevice.IsOpenGLES2 && indexBufferBinding.Is32Bit)
                {
                    throw new PlatformNotSupportedException("32 bits index buffer are not supported on OpenGL ES 2.0");
                }
                indexBufferOffset = (indexBufferId == 0 ? indexBufferBinding.Buffer.StagingData : IntPtr.Zero) +
                                    indexBufferBinding.Offset;
#else
                indexBufferOffset = (IntPtr)indexBufferBinding.Offset;
#endif
                drawElementsType = indexBufferBinding.Is32Bit ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort;
                indexElementSize = indexBufferBinding.Is32Bit ? 4 : 2;
            }

            // If we have a signature, we can already pre-create the instance
            if (preferredInputSignature != null)
            {
                preferredInstance = GetInstance(preferredInputSignature);
            }

            currentShaderSignature = preferredInputSignature;
            currentInstance        = preferredInstance;
        }
 internal bool RequiresApply(EffectInputSignature effectInputSignature)
 {
     return !ReferenceEquals(effectInputSignature, currentShaderSignature);
 }
        /// <summary>
        ///     Prepares a draw call. This method is called before each Draw() method to setup the correct Primitive, InputLayout and VertexBuffers.
        /// </summary>
        /// <param name="primitiveType">Type of the primitive.</param>
        /// <exception cref="System.InvalidOperationException">Cannot GraphicsDevice.Draw*() without an effect being previously applied with Effect.Apply() method</exception>
        private void PrepareDraw(PrimitiveType primitiveType)
        {
            if (CurrentEffect == null)
            {
                throw new InvalidOperationException("Cannot GraphicsDevice.Draw*() without an effect being previously applied with Effect.Apply() method");
            }

            // Setup the primitive type
            PrimitiveType = primitiveType;

            // If the vertex array object is null, simply set the InputLayout to null
            if (newVertexArrayObject == null)
            {
                if (currentVertexArrayObject != null)
                {
                    currentVertexArrayObject = null;
                    currentVertexArrayLayout = null;
                    currentEffectInputSignature = null;
                    inputAssembler.InputLayout = currentInputLayout = null;
                }
            }
            else
            {
                var newVertexArrayLayout = newVertexArrayObject.Layout;
                var newEffectInputSignature = CurrentEffect.InputSignature;
                var oldInputLayout = currentInputLayout;

                // Apply the VertexArrayObject
                if (newVertexArrayObject != currentVertexArrayObject)
                {
                    currentVertexArrayObject = newVertexArrayObject;
                    newVertexArrayObject.Apply(inputAssembler);
                }

                // If the input layout of the effect or the vertex buffer has changed, get the associated new input layout
                if (!ReferenceEquals(newVertexArrayLayout, currentVertexArrayLayout) || !ReferenceEquals(newEffectInputSignature, currentEffectInputSignature))
                {
                    currentVertexArrayLayout = newVertexArrayLayout;
                    currentEffectInputSignature = newEffectInputSignature;

                    if (newVertexArrayObject.InputLayout != null && ReferenceEquals(newEffectInputSignature, newVertexArrayObject.EffectInputSignature))
                    {
                        // Default configuration
                        currentInputLayout = newVertexArrayObject.InputLayout;
                    }
                    else if (ReferenceEquals(newEffectInputSignature, newVertexArrayObject.LastEffectInputSignature))
                    {
                        // Reuse previous configuration
                        currentInputLayout = newVertexArrayObject.LastInputLayout;
                    }
                    // Slow path if the current VertexArrayObject is not optimized for the particular input (or not used right before)
                    else
                    {
                        currentInputLayout = InputLayoutManager.GetInputLayout(newEffectInputSignature, currentVertexArrayLayout);

                        // Store it in VAO since it will likely be used with same effect later
                        newVertexArrayObject.LastInputLayout = currentInputLayout;
                        newVertexArrayObject.LastEffectInputSignature = newEffectInputSignature;
                    }

                    // Setup the input layout (if it changed)
                    if (currentInputLayout != oldInputLayout)
                        inputAssembler.InputLayout = currentInputLayout;
                }
            }

            SetViewportImpl();
        }
        internal void Apply(EffectInputSignature effectInputSignature)
        {
            if (effectInputSignature == null) throw new ArgumentNullException("effectInputSignature");

            // Optimization: If the current VAO and shader signature was previously used, we can use it directly without asking for a proper instance
            if (RequiresApply(effectInputSignature))
            {
                currentInstance = ReferenceEquals(preferredInputSignature, effectInputSignature)
                    ? preferredInstance
                    : GetInstance(effectInputSignature);
                currentShaderSignature = effectInputSignature;
            }

            currentInstance.Apply(GraphicsDevice);
        }
 internal bool RequiresApply(EffectInputSignature effectInputSignature)
 {
     return(!ReferenceEquals(effectInputSignature, currentShaderSignature));
 }
        private void CreateAttributes()
        {
            int vertexAttribCount = 0;
            for (int i = 0; i < vertexBufferBindings.Length; ++i)
            {
                vertexAttribCount += vertexBufferBindings[i].Declaration.VertexElements.Length;
            }

            vertexAttribs = new VertexAttrib[vertexAttribCount];
            int j = 0;
            for (int i = 0; i < vertexBufferBindings.Length; ++i)
            {
                var inputSlot = vertexBufferBindings[i];
                var vertexBuffer = vertexBufferBindings[i].Buffer;

                foreach (var vertexElementAndOffset in inputSlot.Declaration.EnumerateWithOffsets())
                {
                    var vertexElement = vertexElementAndOffset.VertexElement;
                    var attributeName = "a_" + vertexElement.SemanticName + vertexElement.SemanticIndex;

                    var vertexElementFormat = ConvertVertexElementFormat(vertexElement.Format);
#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                    IntPtr bufferStart = vertexBuffer.ResourceId == 0
                        ? vertexBuffer.StagingData
                        : (IntPtr)vertexBufferBindings[i].Offset;
#else
                    var bufferStart = (IntPtr)vertexBufferBindings[i].Offset;
#endif
                    vertexAttribs[j] = new VertexAttrib
                    {
                        VertexBufferId = vertexBuffer.ResourceId,
                        Index = -1,
                        IsInteger = IsInteger(vertexElementFormat.Type),
                        Size = vertexElementFormat.Size,
                        Type = vertexElementFormat.Type,
                        Normalized = vertexElementFormat.Normalized,
                        Stride = inputSlot.Declaration.VertexStride,
                        Offset = bufferStart + vertexElementAndOffset.Offset,
                        AttributeName = attributeName
                    };

                    j++;
                }
            }

            if (indexBufferBinding != null)
            {
                indexBufferId = indexBufferBinding.Buffer.resourceId;

#if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
                if (GraphicsDevice.IsOpenGLES2 && indexBufferBinding.Is32Bit)
                    throw new PlatformNotSupportedException("32 bits index buffer are not supported on OpenGL ES 2.0");
                indexBufferOffset = (indexBufferId == 0 ? indexBufferBinding.Buffer.StagingData : IntPtr.Zero) +
                                    indexBufferBinding.Offset;
#else
                
                indexBufferOffset = (IntPtr)indexBufferBinding.Offset;
#endif
                drawElementsType = indexBufferBinding.Is32Bit ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort;
                indexElementSize = indexBufferBinding.Is32Bit ? 4 : 2;
            }

            // If we have a signature, we can already pre-create the instance
            if (preferredInputSignature != null)
            {
                preferredInstance = GetInstance(preferredInputSignature);
            }

            currentShaderSignature = preferredInputSignature;
            currentInstance = preferredInstance;
        }
 private VertexArrayObjectInstance GetInstance(EffectInputSignature effectInputSignature)
 {
     VertexArrayObjectInstance inputLayout;
     lock (registeredInstances)
     {
         if (!registeredInstances.TryGetValue(effectInputSignature, out inputLayout))
         {
             inputLayout = new VertexArrayObjectInstance(GraphicsDevice, effectInputSignature, vertexAttribs, indexBufferId);
             registeredInstances.Add(effectInputSignature, inputLayout);
         }
     }
     return inputLayout;
 }
 public static VertexArrayObject New(GraphicsDevice graphicsDevice, EffectInputSignature shaderSignature, params VertexBufferBinding[] vertexBufferBindings)
 {
     return(New(graphicsDevice, shaderSignature, null, vertexBufferBindings));
 }
Exemple #33
0
        private void CreateShaders()
        {
            foreach (var shaderBytecode in effectBytecode.Stages)
            {
                var bytecodeRaw = shaderBytecode.Data;
                var reflection  = effectBytecode.Reflection;

                // TODO CACHE Shaders with a bytecode hash
                switch (shaderBytecode.Stage)
                {
                case ShaderStage.Vertex:
                    vertexShader = new VertexShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    // Note: input signature can be reused when reseting device since it only stores non-GPU data,
                    // so just keep it if it has already been created before.
                    if (inputSignature == null)
                    {
                        inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shaderBytecode.Id, bytecodeRaw));
                    }
                    break;

                case ShaderStage.Domain:
                    domainShader = new DomainShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    break;

                case ShaderStage.Hull:
                    hullShader = new HullShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    break;

                case ShaderStage.Geometry:
                    if (reflection.ShaderStreamOutputDeclarations != null && reflection.ShaderStreamOutputDeclarations.Count > 0)
                    {
                        // Calculate the strides
                        var soStrides = new List <int>();
                        foreach (var streamOutputElement in reflection.ShaderStreamOutputDeclarations)
                        {
                            for (int i = soStrides.Count; i < (streamOutputElement.Stream + 1); i++)
                            {
                                soStrides.Add(0);
                            }

                            soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float);
                        }
                        var soElements = new StreamOutputElement[0];     // TODO CREATE StreamOutputElement from bytecode.Reflection.ShaderStreamOutputDeclarations
                        geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw, soElements, soStrides.ToArray(), reflection.StreamOutputRasterizedStream);
                    }
                    else
                    {
                        geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    }
                    break;

                case ShaderStage.Pixel:
                    pixelShader = new PixelShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    break;

                case ShaderStage.Compute:
                    computeShader = new ComputeShader(GraphicsDevice.NativeDevice, bytecodeRaw);
                    break;
                }
            }
        }
 public InputKey(EffectInputSignature effectInputSignature, VertexArrayLayout vertexArrayLayout)
 {
     this.effectInputSignature = effectInputSignature;
     this.vertexArrayLayout    = vertexArrayLayout;
 }
Exemple #35
0
            public SharedData(GraphicsDevice device, EffectInputSignature defaultSignature)
            {
                var vertexBuffer = Buffer.Vertex.New(device, QuadsVertices).DisposeBy(this);
                
                // Register reload
                vertexBuffer.Reload = (graphicsResource) => ((Buffer)graphicsResource).Recreate(QuadsVertices);

                VertexBuffer = VertexArrayObject.New(device, defaultSignature, new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, QuadsVertices.Length, VertexPositionNormalTexture.Size)).DisposeBy(this);
            }
        /// <summary>
        ///     Prepares a draw call. This method is called before each Draw() method to setup the correct Primitive, InputLayout and VertexBuffers.
        /// </summary>
        /// <param name="primitiveType">Type of the primitive.</param>
        /// <exception cref="System.InvalidOperationException">Cannot GraphicsDevice.Draw*() without an effect being previously applied with Effect.Apply() method</exception>
        private void PrepareDraw(PrimitiveType primitiveType)
        {
            if (CurrentEffect == null)
            {
                throw new InvalidOperationException("Cannot GraphicsDevice.Draw*() without an effect being previously applied with Effect.Apply() method");
            }

            // Setup the primitive type
            PrimitiveType = primitiveType;

            // If the vertex array object is null, simply set the InputLayout to null
            if (newVertexArrayObject == null)
            {
                if (currentVertexArrayObject != null)
                {
                    currentVertexArrayObject    = null;
                    currentVertexArrayLayout    = null;
                    currentEffectInputSignature = null;
                    inputAssembler.InputLayout  = currentInputLayout = null;
                }
            }
            else
            {
                var newVertexArrayLayout    = newVertexArrayObject.Layout;
                var newEffectInputSignature = CurrentEffect.InputSignature;
                var oldInputLayout          = currentInputLayout;

                // Apply the VertexArrayObject
                if (newVertexArrayObject != currentVertexArrayObject)
                {
                    currentVertexArrayObject = newVertexArrayObject;
                    newVertexArrayObject.Apply(inputAssembler);
                }

                // If the input layout of the effect or the vertex buffer has changed, get the associated new input layout
                if (!ReferenceEquals(newVertexArrayLayout, currentVertexArrayLayout) || !ReferenceEquals(newEffectInputSignature, currentEffectInputSignature))
                {
                    currentVertexArrayLayout    = newVertexArrayLayout;
                    currentEffectInputSignature = newEffectInputSignature;

                    if (newVertexArrayObject.InputLayout != null && ReferenceEquals(newEffectInputSignature, newVertexArrayObject.EffectInputSignature))
                    {
                        // Default configuration
                        currentInputLayout = newVertexArrayObject.InputLayout;
                    }
                    else if (ReferenceEquals(newEffectInputSignature, newVertexArrayObject.LastEffectInputSignature))
                    {
                        // Reuse previous configuration
                        currentInputLayout = newVertexArrayObject.LastInputLayout;
                    }
                    // Slow path if the current VertexArrayObject is not optimized for the particular input (or not used right before)
                    else
                    {
                        currentInputLayout = InputLayoutManager.GetInputLayout(newEffectInputSignature, currentVertexArrayLayout);

                        // Store it in VAO since it will likely be used with same effect later
                        newVertexArrayObject.LastInputLayout          = currentInputLayout;
                        newVertexArrayObject.LastEffectInputSignature = newEffectInputSignature;
                    }

                    // Setup the input layout (if it changed)
                    if (currentInputLayout != oldInputLayout)
                    {
                        inputAssembler.InputLayout = currentInputLayout;
                    }
                }
            }
        }