kakashidinho / metalangle

MetalANGLE: OpenGL ES to Metal API translation layer
Other
460 stars 64 forks source link

Drawing a single point fails Metal validation #74

Open levinli303 opened 2 years ago

levinli303 commented 2 years ago

I'm using Catalyst version of MetalANGLE, and it seems drawing a single point can fail the Metal validation, the code and error message is as following. When nStars is not 1, it works completely fine.

The stride here is 24, and the three element size are 12 (3 float), 4 (4 byte), 4 (1 * float)

Screen Shot 2021-12-27 at 9 53 07 AM
kakashidinho commented 2 years ago

hey thanks for reporting, could you post your sample code snippet here (in text form)? It could be helpful. cheers,

levinli303 commented 2 years ago

a minimum (and messy) snippet for reproduction. it also reproduces on iOS/iOS Simulator

- (void)prepareGL:(CGSize)size {
    const char *vShaderStr =
      "attribute vec3 inPosition;    \n"
      "attribute vec4 inColor;       \n"
      "attribute float inSize;       \n"
      "varying vec4 color;           \n"
      "void main()                   \n"
      "{                             \n"
      "    color = inColor;          \n"
      "    gl_PointSize = inSize;    \n"
      "    gl_Position = vec4(inPosition, 1.0);    \n"
      "}                             \n";
    const char *fShaderStr =
      "precision mediump float;                                   \n"
      "varying vec4 color;                                        \n"
      "void main()                                                \n"
      "{                                                          \n"
      "     gl_FragColor = color;                                 \n"
      "}                                                          \n";

    GLint compiled;
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderStr, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fShaderStr, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compiled);
    GLint logLength = 0;
    glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
    char* log = malloc(logLength);
    GLsizei charsWritten = 0;
    glGetShaderInfoLog(fragmentShader, logLength, &charsWritten, log);

    GLint linked;
    self.program = glCreateProgram();
    glAttachShader(self.program, vertexShader);
    glAttachShader(self.program, fragmentShader);
    glBindAttribLocation(self.program, 0, "inPosition");
    glBindAttribLocation(self.program, 1, "inSize");
    glBindAttribLocation(self.program, 2, "inColor");
    glLinkProgram(self.program);
    glGetProgramiv(self.program, GL_LINK_STATUS, &linked);
}

- (void)drawGL:(CGSize)size {
    glViewport(0, 0, size.width, size.height);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(self.program);

    static GLuint vboId = 0;

    struct StarVertex
    {
        float position[3];
        float size;
        unsigned char color[4];
        float pad;
    };

    if (vboId == 0)
    {
        struct StarVertex *starCoord = (struct StarVertex *)malloc(sizeof(struct StarVertex) * 1);
        starCoord->position[0] = 0.0f;
        starCoord->position[1] = 0.0f;
        starCoord->position[2] = 0.0f;
        starCoord->color[0] = 255;
        starCoord->color[1] = 0;
        starCoord->color[2] = 0;
        starCoord->color[3] = 255;
        starCoord->size = 20.0f;

        glGenBuffers(1, &vboId);
        glBindBuffer(GL_ARRAY_BUFFER, vboId);
        glBufferData(GL_ARRAY_BUFFER,
                     sizeof(struct StarVertex) * 1,
                     starCoord,
                     GL_STATIC_DRAW);
    }
    else
    {
        glBindBuffer(GL_ARRAY_BUFFER, vboId);
    }

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct StarVertex), __offsetof(struct StarVertex, position));
    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(struct StarVertex), __offsetof(struct StarVertex, size));
    glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(struct StarVertex), __offsetof(struct StarVertex, color));

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glDrawArrays(GL_POINTS, 0, 1);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
}

the validation does not fail if I replace the 1s in these lines of code with 2.

glBufferData(GL_ARRAY_BUFFER, sizeof(struct StarVertex) * 1, starCoord, GL_STATIC_DRAW);
glDrawArrays(GL_POINTS, 0, 1);