OPENGL (GLFW), glDrawElements gives out "Acces.ViolationException"

392 views Asked by At

(I'm a pretty new Coder (at least in Graphics programming), so don't be too harsh with me :( )

Today I tried to render a simple triangle using the C# implementation of OpenGL (GLFW), I followed the web tutorial from "LearnOpenGL.com" specifically the hello triangle tutorial.

I've completed the entire tutorial and expect the program to run and show me a beautifull triangle, instead it gives out the Error message:

_glDrawElements(mode, count, type, indices)
System.AccessViolationException: 'Attempted to read or write protected memory. 
This is often an indication that other memory is corrupt.'"

I searched for a solution, but sadly couldn't find any, I completely checked my code with the tutorial (which is where the error probably is, since I need to "transpose" it from C++ to C#) and couldn't find any errors.

Here's My Code:

class Implementation : App.Game
{

    uint VBO;
    uint VAO;
    uint EBO;
    uint VertexShader;
    uint FragmentShader;
    uint ShaderProgram;

    float[] vertices =
    {
        -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.0f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f
    };

    uint[] indices =
    {
            0, 1, 2,
            1, 2, 3
    };

    public Implementation(int windowWidth, int windowHeight, string windowTitle) : base(windowWidth, windowHeight, windowTitle)
    {
        // StartUp Code hier
    }

    protected override void Initialize()
    {
        // Startet Komponenten und das Spiel
    }

    protected unsafe override void LoadResources()
    {
        // Lädt die hier angegebene Ressourcen

        // ShaderProgram initiieren
        // -
        // Vertex Shader
        VertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(VertexShader, Shader.vertexShader);
        glCompileShader(VertexShader);
        // Shader-Kompilationsfehler Check
        int[] succes = glGetShaderiv(VertexShader, GL_COMPILE_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetShaderInfoLog(VertexShader);
            Debug.WriteLine("VERTEX SHADER COMPILATION ERROR | " + Error);

        }
        // -
        // Fragment Shader
        FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(FragmentShader, Shader.fragmentShader);
        glCompileShader(FragmentShader);
        // Shader-Kompilationsfehler Check
        succes = glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetShaderInfoLog(FragmentShader);
            Debug.WriteLine("FRAGMENT SHADER COMPILATION ERROR | " + Error);

        }
        // -
        // Shader zusammenlinken
        ShaderProgram = glCreateProgram();
        glAttachShader(ShaderProgram, VertexShader);
        glAttachShader(ShaderProgram, FragmentShader);
        glLinkProgram(ShaderProgram);
        // Linker-Fehler Check
        succes = glGetProgramiv(ShaderProgram, GL_LINK_STATUS, 1);
        if (succes[0] == 0)
        {

            string Error = glGetProgramInfoLog(ShaderProgram);
            Debug.WriteLine("SHADER PROGRAM LINKING ERROR | " + Error);

        }
        // Unbenutzte Variablen entfernen
        glDeleteShader(VertexShader);
        glDeleteShader(FragmentShader);

        // Vertex- u. Bufferdaten laden und die Vertex Attribute konfigurieren
        

        glGenVertexArrays(1, (uint*)VAO);
        glGenBuffers(1, (uint*)VBO);
        glGenBuffers(1, (uint*)EBO);

        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        fixed (float* v = &vertices[0])
        { 
            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.Length, v, GL_STATIC_DRAW);
        }

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        fixed (uint* i = &indices[0])
        {
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint) * indices.Length, i, GL_STATIC_DRAW);
        }

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindVertexArray(0);

    }

    protected unsafe override void Render()
    {
        // Render Code hier
        // -
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // -
        // Erstes Dreieck
        glUseProgram(ShaderProgram);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);

        Glfw.SwapBuffers(WindowManager.Window);
        Glfw.PollEvents();

    }

    protected override void Update()
    {
        // Führt auf allen Komponenten und auf dem Spiel die Update funktion durch
    }
}

And here´s the Shader Code:

public static string vertexShader = @"#version 330 core
                                layout (location = 0) in vec3 aPosition;
                                void main() 
                                {
                                    gl_Position = vec4(aPosition.x, aPosition.y, aPosition.z, 1.0);
                                }";

    public static string fragmentShader = @"#version 330 core
                                out vec4 FragColor;
                                void main() 
                                {
                                    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
                                }";

Just for clarification, the background code (LoadResources, Update, Render, Init) all works, I've checked multiple times.

1

There are 1 answers

0
Rabbid76 On BEST ANSWER

The issue are the lines

fixed (float* v = &vertices[0])
fixed (uint* i = &indices[0])

v and i are just a pointer to the 1st elements of the managed arrays.

You have to created Fixed Size Buffers to transfer the data arrays to the GPU. For instance use Marshal.StructureToPtr to marshal data from a managed object to an unmanaged block of memory:

using System.Runtime.InteropServices;
int vertexSize = sizeof(float) * vertices.Length;
IntPtr vertexPtr = Marshal.AllocHGlobal(vertexSize);
Marshal.StructureToPtr(vertices, vertexPtr, false);

glBufferData(GL_ARRAY_BUFFER, vertexSize, vertexPtr, GL_STATIC_DRAW);

Marshal.FreeHGlobal(vertexPtr);

int indexSize = sizeof(float) * vertices.Length;
IntPtr indexPtr = Marshal.AllocHGlobal(indexSize);
Marshal.StructureToPtr(indices, indexPtr, false);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indexPtr, GL_STATIC_DRAW);

Marshal.FreeHGlobal(indexPtr);