Latest OpenGL AMD/NV driver bugs (with repro code) (part II)

Hi all! There are some latest bugs in AMD/NV OpenGL driver:

1. Program queries, that generates GL_INVALID_ENUM on AMD:

glGetProgramiv(glProgram, GL_GEOMETRY_INPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_OUTPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_VERTICES_OUT, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_SHADER_INVOCATIONS, &val);

// where glProgram is valid GL program object

2. Global queries, that generates GL_INVALID_ENUM on AMD:

glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &val);

3. Internal format queries, that generates GL_INVALID_ENUM on AMD:

glGetInternalformativ(any_target, GL_SRGB8, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);
glGetInternalformativ(any_target, GL_SRGB8_ALPHA8, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);
glGetInternalformativ(any_target, GL_RGB9_E5, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);

// NOTE: all this formats are renderable

4. Very old NV glClearBuffer bug:

// leads to GL_INVALID_VALUE on NV with message: <drawbuffer> exceeds the maximum number of supported draw buffers

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBufferfv(GL_COLOR, GL_BACK, color);

// WORKAROUND (but out of spec)

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBufferfv(GL_COLOR, 0, color);

P.S. I hate AMD :confused: Very slow, very buggy driver…

P.P.S. to be continued…

glClearBufferfv(GL_COLOR, GL_BACK, color) is an invalid call.
The second parameter of clear buffer is always an index into the draw-buffers array specified through glDrawBuffers.
That means if you want to clear the back buffer, you have to do the following:

glDrawBuffer(GL_BACK); // this is the default anyways
glClearBufferfv(GL_COLOR, 0, color);

Or a more crazy example:

GLenum drawBuffers[] = { GL_FRONT, GL_BACK };
glDrawBuffers(2, drawBuffers);
glClearBufferfv(GL_COLOR, 1, color);

This is another thing that is for some reason misinterpreted, because the spec language is quite confusing:

If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is specified by passing i as the parameter drawbuffer, and value points to a four-element vector specifying the R, G, B, and A color to clear that draw buffer to. If the draw buffer is one of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying multiple buffers, each selected buffer is cleared to the same value.

Please note here that it says “if the draw buffer is one of FRONT, etc.”, not the drawbuffer parameter as that’s always an index into the draw-buffer array.

[QUOTE=Closed;1240714]glGetInternalformativ(any_target, GL_RGB9_E5, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);

// NOTE: all this formats are renderable[/QUOTE]
No, RGB9_E5 is texture-only color format (according to GL core spec 4.2), it’s not renderable.

I wouldn’t be too sure about that. From section 4.4.4 of the core 4.2 spec:

Table 3.12 clearly lists GL_RGB9_E5 has having a base internal format of “GL_RGB”, which is color-renderable. Therefore, it applies.

I think that’s a spec bug as section 3.9 of the core 4.2 spec (page 215) clearly states otherwise:

  • Texture and renderbuffer color formats (see section 4.4.2).
    – RGBA32F, RGBA32I, RGBA32UI, RGBA16, RGBA16F, RGBA16I, RGBA16UI, RGBA8, RGBA8I, RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_A2UI, RGB5_A1, and RGBA4.
    – R11F_G11F_B10F and RGB565.
    – RG32F, RG32I, RG32UI, RG16, RG16F, RG16I, RG16UI, RG8, RG8I, and RG8UI.
    – R32F, R32I, R32UI, R16F, R16I, R16UI, R16, R8, R8I, and R8UI.
  • Texture-only color formats:
    – RGBA16_SNORM and RGBA8_SNORM.
    – RGB32F, RGB32I, and RGB32UI.
    – RGB16_SNORM, RGB16F, RGB16I, RGB16UI, and RGB16.
    – RGB8_SNORM, RGB8, RGB8I, RGB8UI, and SRGB8.
    – RGB9_E5.
    – RG16_SNORM, RG8_SNORM, COMPRESSED_RG_RGTC2 and COMPRESSED_SIGNED_RG_RGTC2.
    – R16_SNORM, R8_SNORM, COMPRESSED_RED_RGTC1 and COMPRESSED_SIGNED_RED_RGTC1.

An implementation might support those too to be renderable. Like probably the three component formats are supported, or the signed normalized one might be too. However, compressed formats or shared exponent formats are unlikely to be supported (at least on some hardware).

But it doesn’t really matter what is supported or not on a particular hardware, the thing is that the spec does not require it. I doubt that the hardware you’ve used to query RGB9_E5 sample count does support rendering to that format, but you can try :slight_smile:

Also note section 4.4 (page 327):

Implementations are required to support the same internal formats for renderbuffers as the required formats for textures enumerated in section 3.9.3, with the exception
of the color formats labelled “texture-only”.

I think that’s a spec bug as section 3.9 of the core 4.2 spec (page 215) clearly states otherwise:

Different lists for different purposes. Those list describe the formats that implementations must… well, I’ll let the spec explain:

These are internal formats that must be provided more or less as-is. If you ask for GL_R11F_G11F_B10F, the implementation cannot substitute GL_RGBA16F. It may use GL_RGB16F, but it can’t tack on an extra component (or if it does, it has to be invisible to you).

This has nothing to do with the definition of “color-renderable”. Yes, I know that’s stupid, but that’s OpenGL.

The list of formats defined as “color-renderable” is non-negotiable. It is not an implementation-defined property; it’s an inherent property of the enum and the specification. That’s why the error you would get for using a non-color-renderable format is GL_INVALID_ENUM (which is for passing enumerators to a function that the spec says can’t take that enum) rather than GL_INVALID_OPERATION (which is used for more implementation-defined things, or properties that have to do with multiple pieces of state than just the function’s parameters).

Or, to put it another way, “color-renderable” is no guarantee that you can stick it in an FBO and get a complete FBO. A “color-renderable” format is a format that an implementation might allow you to render to, not one that it will. GL_RGB9_E5 is color-renderable, but pretty much no implementation will actually let you do it.

Thanks to all for answers!

1. About RGB9_E5:

Yes it was my fault: RGB9_E5 is texture-only format (p. 217, latest GL4.2 with changes spec), but:
on NV GPUs it is renderable and NV supports MSAA on it (32/16/8/4/2/1 samples), so it is NV bonus (=

2. About ClearBuffer:

It was difficult to see the difference between ‘drawbuffer’ (as parameter) and ‘draw buffer’ (as current draw buffer) in spec text… so it is AMD bug, because:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBuffer(GL_COLOR, 0, color);

leads to ‘no clearing’

WORKAROUND:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBuffer(GL_COLOR, GL_BACK, color);

P.S. So NV +1, AMD -1 (as always) :smiley:

Yes it was my fault: RGB9_E5 is texture-only format (p. 217, latest GL4.2 with changes spec), but

According to section 4.4.4, it is a color-renderable format, and therefore you should not get GL_INVALID_ENUM. What is and is not color-renderable does not change between implementations. That’s what the spec says.

Being color-renderable does not mean that you can stick it in an FBO and have any guarantees of it working.

It does clear, IIRC, even in the correct case, though agree that it should not accept enums. I came across reading the same part of the spec recently because of the same reason. Anyway, the fix will be available in a future driver update :wink:

[QUOTE=Alfonse Reinheart;1240747]According to section 4.4.4, it is a color-renderable format, and therefore you should not get GL_INVALID_ENUM. What is and is not color-renderable does not change between implementations. That’s what the spec says.

Being color-renderable does not mean that you can stick it in an FBO and have any guarantees of it working.[/QUOTE]
Okay, Alfonse, to understand what I mean:
I didn’t say that GL_RGB9_E5 should generate a GL_INVALID_ENUM error, it shouldn’t. I’m just saying it’s not a required renderable format.

WORKAROUND:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBuffer(GL_COLOR, GL_BACK, color);

I think a better workaround, that would work on both AMD and Nvidia cards, is:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(color[0], color[1], color[2], color[3]);
glClear(GL_COLOR_BUFFER_BIT);

[QUOTE=Closed;1240714]1. Program queries, that generates GL_INVALID_ENUM on AMD:

glGetProgramiv(glProgram, GL_GEOMETRY_INPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_OUTPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_VERTICES_OUT, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_SHADER_INVOCATIONS, &val);

// where glProgram is valid GL program object[/QUOTE]
It’s not enough that you have a valid program, the program has to be linked and must contain a geometry shader, otherwise INVALID_OPERATION is generated.

Btw, I’ve checked one of my earlier codes and GL_GEOMETRY_SHADER_INVOCATIONS seem to work properly. Returns invocation count or generates INVALID_OPERATION in case of the condition above.

Are you sure that the error you’ve observed was INVALID_ENUM?

My little finger is telling me that internal AMD drivers already have fixes for what you reported :stuck_out_tongue:

Keep reporting your bugs because chances are that nobody reported this issue before.

Here is the best place for that. This effort will straighten the OpenGL community!

[QUOTE=Closed;1240714]Hi all! There are some latest bugs in AMD/NV OpenGL driver:

1. Program queries, that generates GL_INVALID_ENUM on AMD:

glGetProgramiv(glProgram, GL_GEOMETRY_INPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_OUTPUT_TYPE, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_VERTICES_OUT, &val);
glGetProgramiv(glProgram, GL_GEOMETRY_SHADER_INVOCATIONS, &val);

// where glProgram is valid GL program object

2. Global queries, that generates GL_INVALID_ENUM on AMD:

glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &val);
glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &val);

3. Internal format queries, that generates GL_INVALID_ENUM on AMD:

glGetInternalformativ(any_target, GL_SRGB8, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);
glGetInternalformativ(any_target, GL_SRGB8_ALPHA8, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);
glGetInternalformativ(any_target, GL_RGB9_E5, GL_NUM_SAMPLE_COUNTS / GL_SAMPLES, …);

// NOTE: all this formats are renderable

4. Very old NV glClearBuffer bug:

// leads to GL_INVALID_VALUE on NV with message: <drawbuffer> exceeds the maximum number of supported draw buffers

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBufferfv(GL_COLOR, GL_BACK, color);

// WORKAROUND (but out of spec)

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBufferfv(GL_COLOR, 0, color);

P.S. I hate AMD :confused: Very slow, very buggy driver…

P.P.S. to be continued…[/QUOTE]

[QUOTE=aqnuep;1240768]It’s not enough that you have a valid program, the program has to be linked and must contain a geometry shader…[/QUOTE] Yes of cause, I’m not so stupid :slight_smile:

[QUOTE=aqnuep;1240768]Are you sure that the error you’ve observed was INVALID_ENUM?[/QUOTE] Yep, I’m sure!

In AMD Catalyst 12.7 beta (OGL version 4.2.11740) this is not fixed, except for GL_GEOMETRY_SHADER_INVOCATIONS (this query is working now, phew)

Just be patient…

Standard situation for AMD… all posted bugs are very-very-very old…

Personally, I’ve never seen these particular bugs reported by anyone on this forum. Also, I hardly believe you’ve sent any bug reports to the vendors themselves.

Standard situation for AMD… all posted bugs are very-very-very old…

The age of a bug is from the date it’s reported, not the date it’s been seen. It’s simply not reasonable to expect someone to fix a bug that they don’t know about.