private void CheckFeatures() { GLHelper.ParseGLVersion(GL.GetString(StringName.Version), out GLMajorVersion, out GLMinorVersion, out ESProfile); var glExtensions = new HashSet <string>(GL.GetString(StringName.Extensions).Split(' ')); SupportsTextureRG = !ESProfile || GLMajorVersion >= 3 || glExtensions.Contains("GL_EXT_texture_rg"); SupportsPackedDepth24Stencil8 = !ESProfile || GLMajorVersion >= 3 || glExtensions.Contains("GL_OES_packed_depth_stencil"); SupportsDepth24 = !ESProfile || GLMajorVersion >= 3 || glExtensions.Contains("GL_OES_depth24"); var supportsS3tc = glExtensions.Contains("GL_EXT_texture_compression_s3tc"); SupportsDxt1 = supportsS3tc || glExtensions.Contains("GL_EXT_texture_compression_dxt1"); SupportsDxt3 = supportsS3tc || glExtensions.Contains("GL_ANGLE_texture_compression_dxt3"); SupportsDxt5 = supportsS3tc || glExtensions.Contains("GL_ANGLE_texture_compression_dxt5"); SupportsPvrtc1 = glExtensions.Contains("GL_IMG_texture_compression_pvrtc"); SupportsPvrtc2 = glExtensions.Contains("GL_IMG_texture_compression_pvrtc2"); SupportsEtc1 = glExtensions.Contains("GL_OES_compressed_ETC1_RGB8_texture"); SupportsEtc2 = (ESProfile && GLMajorVersion >= 3) || glExtensions.Contains("GL_ARB_ES3_compatibility"); SupportsInternalFormatBgra8 = ESProfile && glExtensions.Contains("GL_EXT_texture_format_BGRA8888"); SupportsExternalFormatBgra8 = SupportsInternalFormatBgra8 || !ESProfile || glExtensions.Contains("GL_APPLE_texture_format_BGRA8888"); GL.GetInteger(GetPName.MaxCombinedTextureImageUnits, out var maxTextureSlots); GL.GetInteger(GetPName.MaxVertexAttribs, out var maxVertexAttributes); MaxTextureSlots = Math.Min(maxTextureSlots, 32); MaxVertexAttributes = Math.Min(maxVertexAttributes, 64); MaxVertexBufferSlots = MaxVertexAttributes; }
private void BindCullMode(bool force) { if (force || cullMode != boundCullMode) { var enabled = boundCullMode != CullMode.None; var required = cullMode != CullMode.None; if (force || required != enabled) { if (required) { GL.Enable(EnableCap.CullFace); GLHelper.CheckGLErrors(); } else { GL.Disable(EnableCap.CullFace); GLHelper.CheckGLErrors(); } } if (required) { GL.CullFace((CullFaceMode)GLHelper.GetGLCullFaceMode(cullMode)); GLHelper.CheckGLErrors(); } boundCullMode = cullMode; } }
private void BindScissorState(bool force) { scissorStateDirty |= force; if (!scissorStateDirty) { return; } if (force || scissorState.Enable != boundScissorState.Enable) { if (scissorState.Enable) { GL.Enable(EnableCap.ScissorTest); GLHelper.CheckGLErrors(); } else { GL.Disable(EnableCap.ScissorTest); GLHelper.CheckGLErrors(); } boundScissorState.Enable = scissorState.Enable; } if (force || (scissorState.Enable && scissorState.Bounds != boundScissorState.Bounds)) { var bounds = scissorState.Bounds; GL.Scissor(bounds.X, bounds.Y, bounds.Width, bounds.Height); GLHelper.CheckGLErrors(); boundScissorState.Bounds = bounds; } scissorStateDirty = false; }
private void BindViewport(bool force) { viewportDirty |= force; if (!viewportDirty) { return; } if (force || viewport.X != boundViewport.X || viewport.Y != boundViewport.Y || viewport.Width != boundViewport.Width || viewport.Height != boundViewport.Height ) { GL.Viewport(viewport.X, viewport.Y, viewport.Width, viewport.Height); GLHelper.CheckGLErrors(); boundViewport.X = viewport.X; boundViewport.Y = viewport.Y; boundViewport.Width = viewport.Width; boundViewport.Height = viewport.Height; } if (force || viewport.MinDepth != boundViewport.MinDepth || viewport.MaxDepth != boundViewport.MaxDepth ) { GL.DepthRange(viewport.MinDepth, viewport.MaxDepth); GLHelper.CheckGLErrors(); boundViewport.MinDepth = viewport.MinDepth; boundViewport.MaxDepth = viewport.MaxDepth; } viewportDirty = false; }
private void Initialize(TextureParams textureParams) { compressed = Format.IsCompressed(); GLHelper.GetGLTextureFormat(Context, Format, out GLInternalFormat, out GLFormat, out GLPixelType); GLTexture = GL.GenTexture(); GLHelper.CheckGLErrors(); GL.ActiveTexture(TextureUnit.Texture0); GLHelper.CheckGLErrors(); GL.BindTexture(TextureTarget.Texture2D, GLTexture); GLHelper.CheckGLErrors(); for (var level = 0; level < LevelCount; level++) { GraphicsUtility.CalculateMipLevelSize(level, Width, Height, out var levelWidth, out var levelHeight); if (compressed) { var imageSize = GraphicsUtility.CalculateImageDataSize(Format, levelWidth, levelHeight); GL.CompressedTexImage2D(TextureTarget.Texture2D, level, (PixelInternalFormat)GLInternalFormat, levelWidth, levelHeight, 0, imageSize, IntPtr.Zero); GLHelper.CheckGLErrors(); } else { GL.TexImage2D(TextureTarget.Texture2D, level, (PixelInternalFormat)GLInternalFormat, levelWidth, levelHeight, 0, (PixelFormat)GLFormat, (PixelType)GLPixelType, IntPtr.Zero); GLHelper.CheckGLErrors(); } } UpdateTextureParams(textureParams); Context.InvalidateTextureBinding(0); }
public override void Dispose() { if (GLFramebuffer != 0) { GL.DeleteFramebuffer(GLFramebuffer); GLHelper.CheckGLErrors(); GLFramebuffer = 0; } if (GLStencilBuffer != 0) { if (GLStencilBuffer != GLDepthBuffer) { GL.DeleteRenderbuffer(GLStencilBuffer); GLHelper.CheckGLErrors(); } GLStencilBuffer = 0; } if (GLDepthBuffer != 0) { GL.DeleteRenderbuffer(GLDepthBuffer); GLHelper.CheckGLErrors(); GLDepthBuffer = 0; } base.Dispose(); }
private void BindClearValues(bool force, ClearOptions options, Color4 color, float depth, byte stencil) { if ((options & ClearOptions.ColorBuffer) != 0) { if (force || color != boundClearColor) { GL.ClearColor(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); GLHelper.CheckGLErrors(); boundClearColor = color; } } if ((options & ClearOptions.DepthBuffer) != 0) { if (force || depth != boundClearDepth) { GL.ClearDepth(depth); GLHelper.CheckGLErrors(); boundClearDepth = depth; } } if ((options & ClearOptions.StencilBuffer) != 0) { if (force || stencil != boundClearStencil) { GL.ClearStencil(stencil); GLHelper.CheckGLErrors(); boundClearStencil = stencil; } } }
private void BindFrontFace(bool force) { if (force || frontFace != boundFrontFace) { GL.FrontFace((FrontFaceDirection)GLHelper.GetGLFrontFaceDirection(frontFace)); GLHelper.CheckGLErrors(); boundFrontFace = frontFace; } }
public void Dispose() { if (GLShader != 0) { GL.DeleteShader(GLShader); GLHelper.CheckGLErrors(); GLShader = 0; } }
public void ReadPixels(Format format, int x, int y, int width, int height, IntPtr pixels) { GLHelper.GetGLTextureFormat(Context, format, out _, out var glDstFormat, out var glDstType); GL.BindFramebuffer(FramebufferTarget.Framebuffer, GLFramebuffer); GLHelper.CheckGLErrors(); GL.ReadPixels(x, y, width, height, (PixelFormat)glDstFormat, (PixelType)glDstType, pixels); GLHelper.CheckGLErrors(); Context.InvalidateRenderTargetBinding(); }
public void SetTextureParams(TextureParams textureParams) { GL.ActiveTexture(TextureUnit.Texture0); GLHelper.CheckGLErrors(); GL.BindTexture(TextureTarget.Texture2D, GLTexture); GLHelper.CheckGLErrors(); UpdateTextureParams(textureParams); Context.InvalidateTextureBinding(0); }
private void BindShaderProgram() { if (shaderProgramDirty) { GL.UseProgram(shaderProgram.GLProgram); GLHelper.CheckGLErrors(); shaderProgramDirty = false; } shaderProgram.SyncUniforms(); }
public virtual void Dispose() { if (GLTexture != 0) { GL.DeleteTexture(GLTexture); GLHelper.CheckGLErrors(); GLTexture = 0; } Disposed = true; }
public void Dispose() { if (GLBuffer != 0) { GL.DeleteBuffer(GLBuffer); GLHelper.CheckGLErrors(); GLBuffer = 0; } Disposed = true; }
private void EnsureRenderTarget() { if (renderTargetDirty) { var glFramebuffer = renderTarget != null ? renderTarget.GLFramebuffer : glDefaultFramebuffer; GL.BindFramebuffer(FramebufferTarget.Framebuffer, glFramebuffer); GLHelper.CheckGLErrors(); renderTargetDirty = false; } }
public void DrawIndexed(int startIndex, int indexCount, int baseVertex) { PreDraw(baseVertex); var effectiveOffset = indexOffset + startIndex * indexFormat.GetSize(); GL.DrawElements( (PrimitiveType)GLHelper.GetGLPrimitiveType(primitiveTopology), indexCount, (DrawElementsType)GLHelper.GetGLDrawElementsType(indexFormat), new IntPtr(effectiveOffset)); GLHelper.CheckGLErrors(); }
private void BindIndexBuffer() { if (indexBufferDirty) { var glBuffer = indexBuffer != null && !indexBuffer.Disposed ? indexBuffer.GLBuffer : 0; GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer.GLBuffer); GLHelper.CheckGLErrors(); indexBufferDirty = false; } }
private void Initialize() { GLTarget = GetGLBufferTarget(BufferType); GLUsage = Dynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw; GLBuffer = GL.GenBuffer(); GLHelper.CheckGLErrors(); GL.BindBuffer(GLTarget, GLBuffer); GLHelper.CheckGLErrors(); GL.BufferData(GLTarget, Size, IntPtr.Zero, GLUsage); GLHelper.CheckGLErrors(); Context.InvalidateBufferBinding(BufferType); }
public void End() { for (var i = 0; i < MaxVertexAttributes; i++) { var mask = 1L << i; if ((enabledVertexAttribMask & mask) != 0) { GL.DisableVertexAttribArray(i); GLHelper.CheckGLErrors(); } } }
public void Clear(ClearOptions options, Color4 color, float depth, byte stencil) { if (options == ClearOptions.None) { return; } EnsureRenderTarget(); BindClearValues(false, options, color, depth, stencil); ClearBufferMask glClearBufferMask = 0; if ((options & ClearOptions.ColorBuffer) != 0) { glClearBufferMask |= ClearBufferMask.ColorBufferBit; if (boundColorWriteMask != ColorWriteMask.All) { GL.ColorMask(true, true, true, true); GLHelper.CheckGLErrors(); boundColorWriteMask = ColorWriteMask.All; } } if ((options & ClearOptions.DepthBuffer) != 0) { glClearBufferMask |= ClearBufferMask.DepthBufferBit; if (!boundDepthState.WriteEnable) { GL.DepthMask(true); GLHelper.CheckGLErrors(); boundDepthState.WriteEnable = true; depthStateDirty = true; } } if ((options & ClearOptions.StencilBuffer) != 0) { glClearBufferMask |= ClearBufferMask.StencilBufferBit; if (boundStencilState.WriteMask != 0xff) { GL.StencilMask(0xff); GLHelper.CheckGLErrors(); boundStencilState.WriteMask = 0xff; stencilStateDirty = true; } } if (boundScissorState.Enable) { GL.Disable(EnableCap.ScissorTest); GLHelper.CheckGLErrors(); boundScissorState.Enable = false; scissorStateDirty = true; } GL.Clear(glClearBufferMask); GLHelper.CheckGLErrors(); }
private void BindColorWriteMask(bool force) { if (force || colorWriteMask != boundColorWriteMask) { GL.ColorMask( (colorWriteMask & ColorWriteMask.Red) != 0, (colorWriteMask & ColorWriteMask.Green) != 0, (colorWriteMask & ColorWriteMask.Blue) != 0, (colorWriteMask & ColorWriteMask.Alpha) != 0); GLHelper.CheckGLErrors(); boundColorWriteMask = colorWriteMask; } }
public void SetData(int offset, IntPtr data, int size, BufferSetDataMode mode) { GL.BindBuffer(GLTarget, GLBuffer); GLHelper.CheckGLErrors(); if (mode == BufferSetDataMode.Discard) { GL.BufferData(GLTarget, Size, IntPtr.Zero, GLUsage); GLHelper.CheckGLErrors(); } GL.BufferSubData(GLTarget, new IntPtr(offset), size, data); GLHelper.CheckGLErrors(); Context.InvalidateBufferBinding(BufferType); }
private void Initialize( IPlatformShader[] shaders, ShaderProgram.AttribLocation[] attribLocations, ShaderProgram.Sampler[] samplers) { GLProgram = GL.CreateProgram(); GLHelper.CheckGLErrors(); foreach (var shader in shaders) { GL.AttachShader(GLProgram, ((PlatformShader)shader).GLShader); GLHelper.CheckGLErrors(); } foreach (var attribLocation in attribLocations) { GL.BindAttribLocation(GLProgram, attribLocation.Index, attribLocation.Name); GLHelper.CheckGLErrors(); } GL.LinkProgram(GLProgram); GLHelper.CheckGLErrors(); GL.GetProgram(GLProgram, ProgramParameter.LinkStatus, out int linkStatus); GLHelper.CheckGLErrors(); if (linkStatus == 0) { var infoLog = GL.GetProgramInfoLog(GLProgram); GLHelper.CheckGLErrors(); GL.DeleteProgram(GLProgram); GLHelper.CheckGLErrors(); throw new InvalidOperationException($"Shader program link failed:\n{infoLog}"); } GL.UseProgram(GLProgram); GLHelper.CheckGLErrors(); foreach (var sampler in samplers) { var location = GL.GetUniformLocation(GLProgram, sampler.Name); GL.Uniform1(location, sampler.Stage); } Reflect(samplers); uniformStagingData = Marshal.AllocHGlobal(uniformStagingDataSize); dirtyUniformCount = 0; dirtyUniformIndices = new int[uniformInfos.Length]; dirtyUniformElementCount = new int[uniformInfos.Length]; for (var i = 0; i < uniformInfos.Length; i++) { dirtyUniformElementCount[i] = 0; } TextureSlots = uniformInfos .Select(ui => ui.TextureSlot) .Where(slot => slot >= 0) .ToArray(); Context.InvalidateShaderProgramBinding(); }
public void Dispose() { if (uniformStagingData != IntPtr.Zero) { Marshal.FreeHGlobal(uniformStagingData); uniformStagingData = IntPtr.Zero; } if (GLProgram != 0) { GL.DeleteProgram(GLProgram); GLHelper.CheckGLErrors(); GLProgram = 0; } }
private void Initialize(VertexInputLayoutBinding[] bindings, VertexInputLayoutAttribute[] attributes) { var glBindingAttribs = new List <GLVertexInputLayoutAttribute> [bindings.Length]; foreach (var attrib in attributes) { var bindingIndex = Array.FindIndex(bindings, binding => binding.Slot == attrib.Slot); if (bindingIndex < 0) { continue; } GLHelper.GetGLVertexAttribFormat(attrib.Format, out var glType, out var glSize, out var glNormalized); if (glBindingAttribs[bindingIndex] == null) { glBindingAttribs[bindingIndex] = new List <GLVertexInputLayoutAttribute>(); } glBindingAttribs[bindingIndex].Add(new GLVertexInputLayoutAttribute { Index = attrib.Location, Offset = attrib.Offset, Type = glType, Size = glSize, Normalized = glNormalized }); } var glBindings = new List <GLVertexInputLayoutBinding>(); for (var i = 0; i < bindings.Length; i++) { var glAttribs = glBindingAttribs[i]; if (glAttribs != null) { glBindings.Add(new GLVertexInputLayoutBinding { Slot = bindings[i].Slot, Stride = bindings[i].Stride, Attributes = glAttribs.ToArray() }); } } GLBindings = glBindings.ToArray(); foreach (var binding in GLBindings) { BindingMask |= 1L << binding.Slot; foreach (var attrib in binding.Attributes) { AttributeMask |= 1L << attrib.Index; } } }
private void BindTextures() { foreach (var slot in shaderProgram.TextureSlots) { var slotMask = 1 << slot; if ((texturesDirtyMask & slotMask) != 0) { var texture = textures[slot]; var glTexture = texture != null && !texture.Disposed ? texture.GLTexture : 0; GL.ActiveTexture(TextureUnit.Texture0 + slot); GLHelper.CheckGLErrors(); GL.BindTexture(TextureTarget.Texture2D, glTexture); GLHelper.CheckGLErrors(); texturesDirtyMask &= ~slotMask; } } }
private void Initialize(string source) { GLShader = GL.CreateShader(GLHelper.GetGLShaderType(Stage)); GLHelper.CheckGLErrors(); GL.ShaderSource(GLShader, ProcessSource(source)); GLHelper.CheckGLErrors(); GL.CompileShader(GLShader); GLHelper.CheckGLErrors(); GL.GetShader(GLShader, ShaderParameter.CompileStatus, out int compileStatus); if (compileStatus == 0) { var infoLog = GL.GetShaderInfoLog(GLShader); GLHelper.CheckGLErrors(); GL.DeleteShader(GLShader); GLHelper.CheckGLErrors(); throw new System.Exception($"Shader compilation failed:\n{infoLog}"); } }
private void Reflect(ShaderProgram.Sampler[] samplers) { GL.GetProgram(GLProgram, ProgramParameter.ActiveUniforms, out int uniformCount); GLHelper.CheckGLErrors(); GL.GetProgram(GLProgram, ProgramParameter.ActiveUniformMaxLength, out int maxUniformNameLength); GLHelper.CheckGLErrors(); uniformInfos = new UniformInfo[uniformCount]; uniformStagingDataSize = 0; var sb = new StringBuilder(maxUniformNameLength); for (var i = 0; i < uniformCount; i++) { sb.Clear(); GL.GetActiveUniform(GLProgram, i, maxUniformNameLength, out _, out var arraySize, out ActiveUniformType type, sb); GLHelper.CheckGLErrors(); var name = sb.ToString(); var location = GL.GetUniformLocation(GLProgram, name); GLHelper.CheckGLErrors(); var info = new UniformInfo { Name = AdjustUniformName(name), Type = ConvertUniformType(type), ArraySize = arraySize, Location = location, StagingDataOffset = -1, TextureSlot = -1 }; if (info.Type.IsSampler()) { if (info.ArraySize > 1) { throw new NotSupportedException(); } info.TextureSlot = samplers.First(sampler => sampler.Name == info.Name).Stage; } else { info.StagingDataOffset = uniformStagingDataSize; info.ElementSize = 4 * info.Type.GetRowCount() * info.Type.GetColumnCount(); uniformStagingDataSize += info.ElementSize * info.ArraySize; } uniformInfos[i] = info; } }
private void UpdateTextureParams(TextureParams textureParams) { textureParams = textureParams ?? TextureParams.Default; var glMinFilter = LevelCount > 1 ? GLHelper.GetGLTextureFilter(textureParams.MinFilter, textureParams.MipmapMode) : GLHelper.GetGLTextureFilter(textureParams.MinFilter); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)glMinFilter); GLHelper.CheckGLErrors(); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)GLHelper.GetGLTextureFilter(textureParams.MagFilter)); GLHelper.CheckGLErrors(); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)GLHelper.GetGLTextureWrapMode(textureParams.WrapModeU)); GLHelper.CheckGLErrors(); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)GLHelper.GetGLTextureWrapMode(textureParams.WrapModeV)); GLHelper.CheckGLErrors(); }
private void Initialize() { GetGLDepthStencilFormat(out var glDepthFormat, out var glStencilFormat); GLFramebuffer = GL.GenFramebuffer(); GLHelper.CheckGLErrors(); GL.BindFramebuffer(FramebufferTarget.Framebuffer, GLFramebuffer); GLHelper.CheckGLErrors(); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, TextureTarget.Texture2D, GLTexture, 0); GLHelper.CheckGLErrors(); GLDepthBuffer = GLStencilBuffer = 0; if (glDepthFormat != 0) { GLDepthBuffer = GL.GenRenderbuffer(); GLHelper.CheckGLErrors(); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, GLDepthBuffer); GLHelper.CheckGLErrors(); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, (RenderbufferInternalFormat)glDepthFormat, Width, Height); GLHelper.CheckGLErrors(); GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.DepthAttachment, RenderbufferTarget.Renderbuffer, GLDepthBuffer); GLHelper.CheckGLErrors(); } if (glStencilFormat != 0) { GLStencilBuffer = GLDepthBuffer; if (glStencilFormat != glDepthFormat) { GLStencilBuffer = GL.GenRenderbuffer(); GLHelper.CheckGLErrors(); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, GLStencilBuffer); GLHelper.CheckGLErrors(); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, (RenderbufferInternalFormat)glStencilFormat, Width, Height); GLHelper.CheckGLErrors(); } GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.StencilAttachment, RenderbufferTarget.Renderbuffer, GLStencilBuffer); GLHelper.CheckGLErrors(); } CheckFramebufferStatus(); Context.InvalidateRenderTargetBinding(); }