From 5ce1602a17b98fc21c05d692b1094700a9be897a Mon Sep 17 00:00:00 2001 From: thedeadfallgame Date: Thu, 9 May 2024 11:40:48 +0300 Subject: [PATCH 1/4] Buffer.GetData() GLES fix --- .../Graphics/BufferResource.OpenGL.cs | 116 ++++++++---------- .../Platform/Graphics/OpenGL.cs | 26 ++-- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/MonoGame.Framework/Platform/Graphics/BufferResource.OpenGL.cs b/MonoGame.Framework/Platform/Graphics/BufferResource.OpenGL.cs index 89ded9206f0..718ddbeb88f 100644 --- a/MonoGame.Framework/Platform/Graphics/BufferResource.OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/BufferResource.OpenGL.cs @@ -25,8 +25,7 @@ private void PlatformGraphicsDeviceResetting() BufferTarget GetBufferTarget() { - switch (BufferType) - { + switch (BufferType) { case BufferType.StructuredBuffer: return BufferTarget.ShaderStorageBuffer; case BufferType.VertexBuffer: @@ -44,20 +43,18 @@ BufferTarget GetBufferTarget() /// void GenerateIfRequired() { - if (buffer == 0 && ElementStride != 0) - { + if (buffer == 0 && ElementStride != 0) { GL.GenBuffers(1, out this.buffer); GraphicsExtensions.CheckGLError(); GL.BindBuffer(GetBufferTarget(), this.buffer); GraphicsExtensions.CheckGLError(); GL.BufferData(GetBufferTarget(), - new IntPtr(ElementStride * ElementCount), IntPtr.Zero, - _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); + new IntPtr(ElementStride * ElementCount), IntPtr.Zero, + _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } - if (counterBuffer == 0 && StructuredBufferType != StructuredBufferType.Basic) - { + if (counterBuffer == 0 && StructuredBufferType != StructuredBufferType.Basic) { GL.GenBuffers(1, out this.counterBuffer); GraphicsExtensions.CheckGLError(); GL.BindBuffer(BufferTarget.ShaderStorageBuffer, this.counterBuffer); @@ -69,40 +66,34 @@ void GenerateIfRequired() } } - internal void PlatformGetData(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) + internal void PlatformGetData(int offsetInBytes, T[] data, int startIndex, int elementCount, + int vertexStride) where T : struct { -#if GLES - // Buffers are write-only on OpenGL ES 1.1 and 2.0. See the GL_OES_mapbuffer extension for more information. - // http://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt - throw new NotSupportedException("Vertex buffers are write-only on OpenGL ES platforms"); -#else Threading.BlockOnUIThread(() => GetBufferData(offsetInBytes, data, startIndex, elementCount, vertexStride)); -#endif } -#if !GLES private void GetBufferData(int offsetInBytes, T[] data, int startIndex, int elementCount, int elementStride) where T : struct { GL.BindBuffer(GetBufferTarget(), buffer); + GraphicsExtensions.CheckGLError(); // Pointer to the start of data in the vertex buffer - var ptr = GL.MapBuffer(GetBufferTarget(), BufferAccess.ReadOnly); + // Use relative modern glMapBufferRange from + var ptr = GL.MapBufferRange(GetBufferTarget(), 0, elementCount * elementStride, AccessFlags.GlMapReadBit); GraphicsExtensions.CheckGLError(); - ptr = (IntPtr)(ptr.ToInt64() + offsetInBytes); + ptr = (IntPtr) (ptr.ToInt64() + offsetInBytes); - if (typeof(T) == typeof(byte) && elementStride == 1) - { + if (typeof(T) == typeof(byte) && elementStride == 1) { // If data is already a byte[] and stride is 1 we can skip the temporary buffer var buffer = data as byte[]; Marshal.Copy(ptr, buffer, startIndex * elementStride, elementCount * elementStride); } - else - { + else { // Temporary buffer to store the copied section of data var tmp = new byte[elementCount * elementStride]; // Copy from the vertex buffer to the temporary buffer @@ -110,17 +101,14 @@ private void GetBufferData(int offsetInBytes, T[] data, int startIndex, int e // Copy from the temporary buffer to the destination array var tmpHandle = GCHandle.Alloc(tmp, GCHandleType.Pinned); - try - { + try { var tmpPtr = tmpHandle.AddrOfPinnedObject(); - for (var i = 0; i < elementCount; i++) - { - data[startIndex + i] = (T)Marshal.PtrToStructure(tmpPtr, typeof(T)); - tmpPtr = (IntPtr)(tmpPtr.ToInt64() + elementStride); + for (var i = 0; i < elementCount; i++) { + data[startIndex + i] = (T) Marshal.PtrToStructure(tmpPtr, typeof(T)); + tmpPtr = (IntPtr) (tmpPtr.ToInt64() + elementStride); } } - finally - { + finally { tmpHandle.Free(); } } @@ -129,10 +117,9 @@ private void GetBufferData(int offsetInBytes, T[] data, int startIndex, int e GraphicsExtensions.CheckGLError(); } -#endif - internal void PlatformSetData( - int offsetInBytes, T[] data, int startIndex, int elementCount, int elementStride, SetDataOptions options, int bufferSize, int elementSizeInBytes) + int offsetInBytes, T[] data, int startIndex, int elementCount, int elementStride, SetDataOptions options, + int bufferSize, int elementSizeInBytes) where T : struct { Threading.BlockOnUIThread(SetDataState.Action, new SetDataState @@ -150,7 +137,8 @@ internal void PlatformSetData( } private void PlatformSetDataBody( - int offsetInBytes, T[] data, int startIndex, int elementCount, int elementStride, SetDataOptions options, int bufferSize, int elementSizeInBytes) + int offsetInBytes, T[] data, int startIndex, int elementCount, int elementStride, SetDataOptions options, + int bufferSize, int elementSizeInBytes) where T : struct { GenerateIfRequired(); @@ -158,55 +146,49 @@ private void PlatformSetDataBody( GL.BindBuffer(GetBufferTarget(), buffer); GraphicsExtensions.CheckGLError(); - if (options == SetDataOptions.Discard) - { + if (options == SetDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData( GetBufferTarget(), - (IntPtr)bufferSize, + (IntPtr) bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } var elementSizeInByte = Marshal.SizeOf(); - if (elementSizeInByte == elementStride || elementSizeInByte % elementStride == 0) - { + if (elementSizeInByte == elementStride || elementSizeInByte % elementStride == 0) { // there are no gaps so we can copy in one go var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes); + try { + var dataPtr = + (IntPtr) (dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes); - GL.BufferSubData(GetBufferTarget(), (IntPtr)offsetInBytes, (IntPtr)(elementSizeInBytes * elementCount), dataPtr); + GL.BufferSubData(GetBufferTarget(), (IntPtr) offsetInBytes, + (IntPtr) (elementSizeInBytes * elementCount), dataPtr); GraphicsExtensions.CheckGLError(); } - finally - { + finally { dataHandle.Free(); } } - else - { + else { // else we must copy each element separately var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { + try { int dstOffset = offsetInBytes; - var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); + var dataPtr = (IntPtr) (dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); - for (int i = 0; i < elementCount; i++) - { - GL.BufferSubData(GetBufferTarget(), (IntPtr)dstOffset, (IntPtr)elementSizeInByte, dataPtr); + for (int i = 0; i < elementCount; i++) { + GL.BufferSubData(GetBufferTarget(), (IntPtr) dstOffset, (IntPtr) elementSizeInByte, dataPtr); GraphicsExtensions.CheckGLError(); dstOffset += elementStride; - dataPtr = (IntPtr)(dataPtr.ToInt64() + elementSizeInByte); + dataPtr = (IntPtr) (dataPtr.ToInt64() + elementSizeInByte); } } - finally - { + finally { dataHandle.Free(); } } @@ -217,35 +199,34 @@ private void SetCounterBufferValue(int val) GL.BindBuffer(BufferTarget.ShaderStorageBuffer, counterBuffer); GraphicsExtensions.CheckGLError(); - unsafe - { + unsafe { int* data = stackalloc int[1]; data[0] = val; - GL.BufferSubData(BufferTarget.ShaderStorageBuffer, IntPtr.Zero, new IntPtr(4), (IntPtr)data); + GL.BufferSubData(BufferTarget.ShaderStorageBuffer, IntPtr.Zero, new IntPtr(4), (IntPtr) data); GraphicsExtensions.CheckGLError(); } } - internal override void PlatformApply(GraphicsDevice device, ShaderProgram program, ref ResourceBinding resourceBinding, bool writeAcess) + internal override void PlatformApply(GraphicsDevice device, ShaderProgram program, + ref ResourceBinding resourceBinding, bool writeAcess) { GL.BindBufferBase(BufferTarget.ShaderStorageBuffer, resourceBinding.bindingSlot, buffer); GraphicsExtensions.CheckGLError(); - - if (counterBuffer > 0) - { + + if (counterBuffer > 0) { if (CounterBufferResetValue != -1) SetCounterBufferValue(CounterBufferResetValue); - GL.BindBufferBase(BufferTarget.ShaderStorageBuffer, resourceBinding.bindingSlotForCounter, counterBuffer); + GL.BindBufferBase(BufferTarget.ShaderStorageBuffer, resourceBinding.bindingSlotForCounter, + counterBuffer); GraphicsExtensions.CheckGLError(); } } protected override void Dispose(bool disposing) { - if (!IsDisposed) - { + if (!IsDisposed) { if (GraphicsDevice != null) GraphicsDevice.DisposeBuffer(buffer); } @@ -268,7 +249,8 @@ struct SetDataState public static Action> Action = (s) => { s.buffer.PlatformSetDataBody( - s.offsetInBytes, s.data, s.startIndex, s.elementCount, s.elementStride, s.options, s.bufferSize, s.elementSizeInBytes); + s.offsetInBytes, s.data, s.startIndex, s.elementCount, s.elementStride, s.options, s.bufferSize, + s.elementSizeInBytes); }; } } diff --git a/MonoGame.Framework/Platform/Graphics/OpenGL.cs b/MonoGame.Framework/Platform/Graphics/OpenGL.cs index 78b09714632..da422105455 100644 --- a/MonoGame.Framework/Platform/Graphics/OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/OpenGL.cs @@ -441,7 +441,7 @@ internal enum PixelInternalFormat Rgba16f = 0x881A, R16f = 0x822D, Rg32f = 0x8230, - Rgba32f = 0x8814, + Rgba32f = 0x8814, R8ui = 0x8232, R8i = 0x8231, R16ui = 0x8234, @@ -506,9 +506,9 @@ internal enum PixelType Float = 0x1406, HalfFloat = 0x140B, HalfFloatOES = 0x8D61, - Byte = 0x1400, - Short = 0x1402, - Int = 0x1404, + Byte = 0x1400, + Short = 0x1402, + Int = 0x1404, UnsignedShort = 0x1403, UnsignedInt = 0x1405, UnsignedInt1010102 = 0x8036, @@ -609,6 +609,11 @@ internal enum MemoryBarrierBits : uint All = 0xFFFFFFFF, } + internal enum AccessFlags : uint + { + GlMapReadBit = 0x1, + } + internal partial class ColorFormat { internal ColorFormat (int r, int g, int b, int a) @@ -1401,6 +1406,12 @@ internal delegate void TexSubImage3DDelegate(TextureTarget target, int level, internal delegate IntPtr MapBufferDelegate(BufferTarget target, BufferAccess access); internal static MapBufferDelegate MapBuffer; + [System.Security.SuppressUnmanagedCodeSecurity()] + [UnmanagedFunctionPointer(callingConvention)] + [MonoNativeFunctionWrapper] + internal delegate IntPtr MapBufferRangeDelegate(BufferTarget target, IntPtr offset, IntPtr size, AccessFlags access); + internal static MapBufferRangeDelegate MapBufferRange; + [System.Security.SuppressUnmanagedCodeSecurity()] [UnmanagedFunctionPointer(callingConvention)] [MonoNativeFunctionWrapper] @@ -1543,10 +1554,10 @@ internal static void LoadEntryPoints () UniformMatrix4fv = LoadFunction ("glUniformMatrix4fv"); UniformMatrix2x3fv = LoadFunction ("glUniformMatrix2x3fv"); UniformMatrix2x4fv = LoadFunction ("glUniformMatrix2x4fv"); - UniformMatrix3x2fv = LoadFunction ("glUniformMatrix3x2fv"); + UniformMatrix3x2fv = LoadFunction ("glUniformMatrix3x2fv"); UniformMatrix3x4fv = LoadFunction ("glUniformMatrix3x4fv"); UniformMatrix4x2fv = LoadFunction ("glUniformMatrix4x2fv"); - UniformMatrix4x3fv = LoadFunction ("glUniformMatrix4x3fv"); + UniformMatrix4x3fv = LoadFunction ("glUniformMatrix4x3fv"); ReadPixelsInternal = LoadFunction ("glReadPixels"); @@ -1629,6 +1640,7 @@ internal static void LoadEntryPoints () GenBuffers = LoadFunction ("glGenBuffers"); BufferData = LoadFunction ("glBufferData"); MapBuffer = LoadFunction ("glMapBuffer"); + MapBufferRange = LoadFunction ("glMapBufferRange"); UnmapBuffer = LoadFunction ("glUnmapBuffer"); BufferSubData = LoadFunction ("glBufferSubData"); DeleteBuffers = LoadFunction ("glDeleteBuffers"); @@ -1701,7 +1713,7 @@ internal static void LoadExtensions() GL.LoadFrameBufferObjectEXTEntryPoints(); } if (GL.RenderbufferStorageMultisample == null) - { + { if (Extensions.Contains("GL_APPLE_framebuffer_multisample")) { GL.RenderbufferStorageMultisample = LoadFunction("glRenderbufferStorageMultisampleAPPLE"); From 204de634b9eb9ac80f7c040c77c7e177436bf3f4 Mon Sep 17 00:00:00 2001 From: k4G17eYWI Date: Fri, 10 May 2024 15:14:14 +0200 Subject: [PATCH 2/4] VAO --- .../Graphics/GraphicsDevice.OpenGL.cs | 43 +++++++++++-------- .../Platform/Graphics/OpenGL.cs | 20 +++++++++ 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs index aa955611909..0df85062dde 100644 --- a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs @@ -227,7 +227,7 @@ private void ApplyAttribs(Shader shader, int baseVertex) (IntPtr)(offset.ToInt64() + element.Offset)); // only set the divisor if instancing is supported - if (GraphicsCapabilities.SupportsInstancing) + if (GraphicsCapabilities.SupportsInstancing) GL.VertexAttribDivisor(element.AttributeLocation, vertexBufferBinding.InstanceFrequency); GraphicsExtensions.CheckGLError(); @@ -348,7 +348,7 @@ private void PlatformInitialize() // Ensure the vertex attributes are reset _enabledVertexAttributes.Clear(); - // Free all the cached shader programs. + // Free all the cached shader programs. _programCache.Clear(); _shaderProgram = null; @@ -363,7 +363,7 @@ private void PlatformInitialize() for (int i = 0; i < _bufferBindingInfos.Length; i++) _bufferBindingInfos[i] = new BufferBindingInfo(null, IntPtr.Zero, 0, -1); } - + private DepthStencilState clearDepthStencilState = new DepthStencilState { StencilEnable = true }; private void PlatformClear(ClearOptions options, Vector4 color, float depth, int stencil) @@ -386,7 +386,7 @@ private void PlatformClear(ClearOptions options, Vector4 color, float depth, int var prevDepthStencilState = DepthStencilState; var prevBlendState = BlendState; ScissorRectangle = _viewport.Bounds; - // DepthStencilState.Default has the Stencil Test disabled; + // DepthStencilState.Default has the Stencil Test disabled; // make sure stencil test is enabled before we clear since // some drivers won't clear with stencil test disabled DepthStencilState = this.clearDepthStencilState; @@ -415,7 +415,7 @@ private void PlatformClear(ClearOptions options, Vector4 color, float depth, int bufferMask = bufferMask | ClearBufferMask.StencilBufferBit; } - if ((options & ClearOptions.DepthBuffer) == ClearOptions.DepthBuffer) + if ((options & ClearOptions.DepthBuffer) == ClearOptions.DepthBuffer) { if (depth != _lastClearDepth) { @@ -435,7 +435,7 @@ private void PlatformClear(ClearOptions options, Vector4 color, float depth, int #if MONOMAC || IOS } #endif - + // Restore the previous render state. ScissorRectangle = prevScissorRect; DepthStencilState = prevDepthStencilState; @@ -572,7 +572,7 @@ private void PlatformSetViewport(ref Viewport value) GL.DepthRange(value.MinDepth, value.MaxDepth); GraphicsExtensions.LogGLError("GraphicsDevice.Viewport_set() GL.DepthRange"); - + // In OpenGL we have to re-apply the special "posFixup" // vertex shader uniform if the viewport changes. _vertexShaderDirty = true; @@ -644,12 +644,14 @@ public int GetHashCode(RenderTargetBinding[] array) // FBO cache used to resolve MSAA rendertargets, we create 1 FBO per RenderTargetBinding combination private Dictionary glResolveFramebuffers = new Dictionary(new RenderTargetBindingArrayComparer()); + private bool _vaoCreated; + internal void PlatformCreateRenderTarget(IRenderTarget renderTarget, int width, int height, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) { var color = 0; var depth = 0; var stencil = 0; - + if (preferredMultiSampleCount > 0 && this.framebufferHelper.SupportsBlitFramebuffer) { this.framebufferHelper.GenRenderbuffer(out color); @@ -663,7 +665,7 @@ internal void PlatformCreateRenderTarget(IRenderTarget renderTarget, int width, var stencilInternalFormat = (RenderbufferStorage)0; switch (preferredDepthFormat) { - case DepthFormat.Depth16: + case DepthFormat.Depth16: depthInternalFormat = RenderbufferStorage.DepthComponent16; break; #if GLES @@ -947,7 +949,7 @@ private static GLPrimitiveType PrimitiveTypeGL(PrimitiveType primitiveType) } /// - /// Activates the Current Vertex/Pixel shader pair into a program. + /// Activates the Current Vertex/Pixel shader pair into a program. /// private unsafe void ActivateShaderProgram() { @@ -1129,7 +1131,7 @@ internal void PlatformApplyState(bool applyShaders) _geometryConstantBuffers.SetConstantBuffers(this, _shaderProgram); GeometryShaderResources.PlatformApplyAllResourcesToDevice(this, _shaderProgram); GeometrySamplerStates.PlatformSetSamplers(this, _geometryShader, GeometryShaderResources); - } + } } private void PlatformDrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, int startIndex, int primitiveCount) @@ -1198,7 +1200,7 @@ private void PlatformDrawUserPrimitives( private void PlatformDrawPrimitives(PrimitiveType primitiveType, int vertexStart, int vertexCount) { - ApplyState(true); + ApplyState(true); ApplyAttribs(_vertexShader, 0); @@ -1348,7 +1350,7 @@ private void PlatformDrawInstancedPrimitives(PrimitiveType primitiveType, int ba GraphicsExtensions.CheckGLError(); } - + private void PlatformDrawInstancedPrimitivesIndirect(PrimitiveType primitiveType, IndirectDrawBuffer indirectDrawBuffer, int alignedByteOffsetForArgs) { if (!GraphicsCapabilities.SupportsInstancing) @@ -1358,6 +1360,13 @@ private void PlatformDrawInstancedPrimitivesIndirect(PrimitiveType primitiveType ApplyAttribs(_vertexShader, 0); + if (!_vaoCreated) { + UIntPtr vao = new UIntPtr(4); + GL.GenVertexArrays(1, vao); + //GL.BindVertexArray(vao); + _vaoCreated = true; + } + // Set vertex count for tesselation patch var primitiveTypeGL = PrimitiveTypeGL(primitiveType); if (primitiveTypeGL == GLPrimitiveType.Patches) @@ -1413,7 +1422,7 @@ private void PlatformDispatchCompute(int threadGroupCountX, int threadGroupCount GraphicsExtensions.CheckGLError(); // The memory barrier will ensure that data written by the compute shader will be visible when other shaders read that data later. - // Better performance can probably be achievable by using only the required bits, and only when it's actually neccessary. + // Better performance can probably be achievable by using only the required bits, and only when it's actually neccessary. GL.MemoryBarrier(MemoryBarrierBits.All); GraphicsExtensions.CheckGLError(); } @@ -1429,7 +1438,7 @@ private void PlatformDispatchComputeIndirect(IndirectDrawBuffer indirectDrawBuff GraphicsExtensions.CheckGLError(); // The memory barrier will ensure that data written by the compute shader will be visible when other shaders read that data later. - // Better performance can probably be achievable by using only the required bits, and only when it's actually neccessary. + // Better performance can probably be achievable by using only the required bits, and only when it's actually neccessary. GL.MemoryBarrier(MemoryBarrierBits.All); GraphicsExtensions.CheckGLError(); } @@ -1510,7 +1519,7 @@ private static Rectangle PlatformGetTitleSafeArea(int x, int y, int width, int h { return new Rectangle(x, y, width, height); } - + internal void PlatformSetMultiSamplingToMaximum(PresentationParameters presentationParameters, out int quality) { presentationParameters.MultiSampleCount = 4; @@ -1569,7 +1578,7 @@ private void GetDisplayResolution(out int width, out int height) height = mode.Height; } #endif - + } } diff --git a/MonoGame.Framework/Platform/Graphics/OpenGL.cs b/MonoGame.Framework/Platform/Graphics/OpenGL.cs index da422105455..34d80765c5d 100644 --- a/MonoGame.Framework/Platform/Graphics/OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/OpenGL.cs @@ -1475,6 +1475,23 @@ internal delegate void DrawElementsInstancedBaseInstanceDelegate(GLPrimitiveType internal delegate void MemoryBarrierDelegate(MemoryBarrierBits barriers); internal static MemoryBarrierDelegate MemoryBarrier; + /**********************************************************************************/ + + [System.Security.SuppressUnmanagedCodeSecurity()] + [UnmanagedFunctionPointer(callingConvention)] + [MonoNativeFunctionWrapper] + internal delegate void GenVertexArraysDelegate(int n, UIntPtr size); + internal static GenVertexArraysDelegate GenVertexArrays; + + [System.Security.SuppressUnmanagedCodeSecurity()] + [UnmanagedFunctionPointer(callingConvention)] + [MonoNativeFunctionWrapper] + internal delegate void BindVertexArrayDelegate(UIntPtr vao); + internal static BindVertexArrayDelegate BindVertexArray; + + /**********************************************************************************/ + + #if DEBUG [UnmanagedFunctionPointer (CallingConvention.StdCall)] delegate void DebugMessageCallbackProc (int source, int type, int id, int severity, int length, IntPtr message, IntPtr userParam); @@ -1645,6 +1662,9 @@ internal static void LoadEntryPoints () BufferSubData = LoadFunction ("glBufferSubData"); DeleteBuffers = LoadFunction ("glDeleteBuffers"); + GenVertexArrays = LoadFunction ("glGenVertexArrays"); + BindVertexArray = LoadFunction ("glBindVertexArray"); + VertexAttribPointer = LoadFunction ("glVertexAttribPointer"); PatchParameteri = LoadFunction("glPatchParameteri"); From cbc466e12d8f335e391afdb6396122fd3ef4f290 Mon Sep 17 00:00:00 2001 From: k4G17eYWI Date: Fri, 10 May 2024 22:45:21 +0200 Subject: [PATCH 3/4] VAO --- .../Graphics/GraphicsDevice.OpenGL.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs index 0df85062dde..b942887d08d 100644 --- a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs @@ -362,6 +362,15 @@ private void PlatformInitialize() _bufferBindingInfos = new BufferBindingInfo[_maxVertexBufferSlots]; for (int i = 0; i < _bufferBindingInfos.Length; i++) _bufferBindingInfos[i] = new BufferBindingInfo(null, IntPtr.Zero, 0, -1); + + // Create VAO + // Indirect drawing does not work without VAO on some platforms (Android for instance) + // (for some reason this does not work for a scalar, works only for an array) + var a = new uint[1]; + var dataPtr = GCHandle.Alloc(a, GCHandleType.Pinned); + var vao = (UIntPtr) dataPtr.AddrOfPinnedObject(); + GL.GenVertexArrays(1, vao); + GL.BindVertexArray(a[0]); } private DepthStencilState clearDepthStencilState = new DepthStencilState { StencilEnable = true }; @@ -644,8 +653,6 @@ public int GetHashCode(RenderTargetBinding[] array) // FBO cache used to resolve MSAA rendertargets, we create 1 FBO per RenderTargetBinding combination private Dictionary glResolveFramebuffers = new Dictionary(new RenderTargetBindingArrayComparer()); - private bool _vaoCreated; - internal void PlatformCreateRenderTarget(IRenderTarget renderTarget, int width, int height, bool mipMap, SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat, int preferredMultiSampleCount, RenderTargetUsage usage) { var color = 0; @@ -1356,16 +1363,13 @@ private void PlatformDrawInstancedPrimitivesIndirect(PrimitiveType primitiveType if (!GraphicsCapabilities.SupportsInstancing) throw new PlatformNotSupportedException("Instanced geometry drawing requires at least OpenGL 3.2 or GLES 3.2. Try upgrading your graphics card drivers."); + GraphicsExtensions.CheckGLError(); + ApplyState(true); ApplyAttribs(_vertexShader, 0); - if (!_vaoCreated) { - UIntPtr vao = new UIntPtr(4); - GL.GenVertexArrays(1, vao); - //GL.BindVertexArray(vao); - _vaoCreated = true; - } + // Set vertex count for tesselation patch var primitiveTypeGL = PrimitiveTypeGL(primitiveType); From 35c58322aef34248facbf24a1d52b666e385ce7d Mon Sep 17 00:00:00 2001 From: k4G17eYWI Date: Fri, 10 May 2024 23:05:44 +0200 Subject: [PATCH 4/4] Checking if functions exist --- .../Platform/Graphics/GraphicsDevice.OpenGL.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs index b942887d08d..18604cc000a 100644 --- a/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/GraphicsDevice.OpenGL.cs @@ -365,12 +365,15 @@ private void PlatformInitialize() // Create VAO // Indirect drawing does not work without VAO on some platforms (Android for instance) - // (for some reason this does not work for a scalar, works only for an array) - var a = new uint[1]; - var dataPtr = GCHandle.Alloc(a, GCHandleType.Pinned); - var vao = (UIntPtr) dataPtr.AddrOfPinnedObject(); - GL.GenVertexArrays(1, vao); - GL.BindVertexArray(a[0]); + // Check if function exist + if (GL.GenVertexArrays != null && GL.BindVertexArray != null) { + // (for some reason this does not work for a scalar, works only for an array) + var a = new uint[1]; + var dataPtr = GCHandle.Alloc(a, GCHandleType.Pinned); + var vao = (UIntPtr) dataPtr.AddrOfPinnedObject(); + GL.GenVertexArrays(1, vao); + GL.BindVertexArray(a[0]); + } } private DepthStencilState clearDepthStencilState = new DepthStencilState { StencilEnable = true };