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