[Piglit] [PATCH] EXT_multisampled_render_to_texture: functional test

Wendt, Magnus magnus.wendt at intel.com
Tue Jan 12 12:40:49 PST 2016


Thank you Ian for the review and helpful comments.

My apologies for not getting the reply done before the holidays. To keep the mail short I have not replied to any comments you had that I just fixed according to your suggestions. So consider all that addressed.

>> [blitting from a multisampled FBO to a singlesampled one and then to the default framebuffer]
> It seems like this could be simpler... can you make fbo_ms half the width of the default framebuffer and just resolve directly from fbo_ms to the default framebuffer?

My reason for doing it this way is that it reflects how multisampled render to texture is done without the extension. Sometimes when writing tests you get to write convoluted code for the sake of being convoluted ;). I have modified the final draw_rect to not being axis aligned anymore so that this second FBO is actually required. 

>> +		if (!piglit_probe_rect_halves_equal_rgba(0, 0, FB_WIDTH, FB_HEIGHT))
> Does the spec actually require that the results be identical?

Not really, but I expect that any implementation would most likely implement it that way. Since this isn't a conformance test, but a functional test, I took the pragmatic approach and tested for identity rather than trying to tune tolerance levels to e.g. reject single sampled results. If anyone implements this extension in a way so that the identity assumption doesn't hold anymore the test could be updated at that time.

> Avoid tests that overdraw previous results. [...]

In this case overdrawing is the test. I want to make sure that there are no nasty interactions with fast clear. But I agree the result should remain intact, so I have added a break if a pass fails. (Other than overdraw the additional passes don't really do anything interesting.)

>> +	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
>> +	                          GL_RENDERBUFFER, fbo_ms.depth);
> Do you actually need a depth buffer?

Yes and no. I have removed the depth buffer from the default framebuffer. As for the FBOs: I am creating an FBO with a multisampled depth attachment and a single sampled color attachment. I think that is exotic enough to warrant a depth buffer. As for the ground truth FBO, I have it just for symmetry reasons.

Sending a v2.

- Magnus

-----Original Message-----
From: Ian Romanick [mailto:idr at freedesktop.org] 
Sent: Thursday, December 17, 2015 10:02 PM
To: Wendt, Magnus <magnus.wendt at intel.com>; piglit at lists.freedesktop.org
Subject: Re: [Piglit] [PATCH] EXT_multisampled_render_to_texture: functional test

On 12/16/2015 06:33 AM, Magnus Wendt wrote:
> EXT_multisampled_render_to_texture allows you to bind a singlesampled 
> texture to the color attachment of a multisampled framebuffer object.
> Rendering is multisampled and the multisample data is implicitly 
> resolved and invalidated when texturing.
> 
> The test renders a ground truth image by drawing a slanted textured 
> quad to a multisampled fbo and resolves it using a blit to a 
> singlesampled fbo. This is textured onto the left half of the window.
> It then renders the same thing into an implicitly resolved fbo and 
> textures that onto the right half of the screen. The two halfs are 
> compared. This is repeated for another slant and different clear 
> colors to check for possible interactions with fast clear.
> The test passes if the two methods yeild identical results for all 
> image

                                     yield

> pairs.

We'll also need a couple additional tests.  At the very least, we need an api-errors test.  There are many that you can borrow from.

    If RenderbufferStorageMultisampleEXT is called with a value of
    <samples> that is greater than MAX_SAMPLES_EXT, then the error
    INVALID_VALUE is generated.

    The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT 
    is called with a <target> that is not FRAMEBUFFER.

    The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT
    is called with an <attachment> that is not COLOR_ATTACHMENT0.

    The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT 
    is called with a <textarget> that is not TEXTURE_2D, 
    TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, 
    TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X, 
    TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z.

The errors section neglects to mention this error from earlier in the spec:

    If either width or height is greater than the value of
    MAX_RENDERBUFFER_SIZE ... then the error INVALID_VALUE is generated.

We also need a minmax test for GL_MAX_SAMPLES_EXT.  Copy from tests/spec/arb_shader_subroutine/minmax.c.

I'd also like to see a test for this bit:

        Otherwise samples represents a request for a desired minimum number 
        of samples. Since different implementations may support different 
        sample counts for multisampled rendering, the actual number of samples 
        allocated for the renderbuffer image is implementation-dependent. 
        However, the resulting value for RENDERBUFFER_SAMPLES_EXT is 
        guaranteed to be greater than or equal to samples and no more than the
        next larger sample count supported by the implementation.

On GLES3, the set of possible sample counts can be determined using

    glGetInternalformativ(GL_RENDERBUFFER, /* or GL_TEXTURE_2D_MULTISAMPLE */
                          GL_RGB8,
                          GL_SAMPLES,
                          ARRAY_SIZE(buffer),
                          buffer);

> Signed-off-by: Magnus Wendt <magnus.wendt at intel.com>
> ---
>  tests/all.py                                       |   7 +
>  tests/spec/CMakeLists.txt                          |   1 +
>  .../CMakeLists.gles3.txt                           |   5 +
>  .../CMakeLists.txt                                 |   1 +
>  .../ext_multisampled_render_to_texture.c           | 367 +++++++++++++++++++++
>  5 files changed, 381 insertions(+)
>  create mode 100644 
> tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
>  create mode 100644 
> tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
>  create mode 100644 
> tests/spec/ext_multisampled_render_to_texture/ext_multisampled_render_
> to_texture.c
> 
> diff --git a/tests/all.py b/tests/all.py index f61ff15..c17450b 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -4552,5 +4552,12 @@ with profile.group_manager(
>      for sample_count in (str(x) for x in MSAA_SAMPLE_COUNTS):
>          g(['ext_shader_samples_identical', sample_count])
>  
> +# Group EXT_multismapled_render_to_texture
> +with profile.group_manager(
> +        PiglitGLTest,
> +        grouptools.join('spec', 'ext_multisampled_render_to_texture')) as g:
> +    for sample_count in (str(x) for x in MSAA_SAMPLE_COUNTS):
> +        g(['ext_multisampled_render_to_texture', sample_count])
> +
>  if platform.system() is 'Windows':
>      profile.filter_tests(lambda p, _: not p.startswith('glx')) diff 
> --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index 
> 57ac541..21ec666 100644
> --- a/tests/spec/CMakeLists.txt
> +++ b/tests/spec/CMakeLists.txt
> @@ -75,6 +75,7 @@ add_subdirectory (ext_depth_bounds_test)  
> add_subdirectory (ext_fog_coord)  add_subdirectory 
> (ext_framebuffer_multisample)  add_subdirectory 
> (ext_framebuffer_multisample_blit_scaled)
> +add_subdirectory (ext_multisampled_render_to_texture)
>  add_subdirectory (ext_packed_depth_stencil)  add_subdirectory 
> (ext_packed_float)  add_subdirectory (ext_shader_samples_identical) 
> diff --git 
> a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt 
> b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
> new file mode 100644
> index 0000000..fbb688c
> --- /dev/null
> +++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.t
> +++ xt
> @@ -0,0 +1,5 @@
> +link_libraries(
> +	piglitutil_${piglit_target_api}
> +	)
> +
> +piglit_add_executable(ext_multisampled_render_to_texture 
> +ext_multisampled_render_to_texture.c)

Since there are going to be multiple tests, you're going to need to change this name.  The usual piglit pattern is to name the source file something descriptive like render.c, and name the executable extension_name-source_name.

> diff --git 
> a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt 
> b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
> new file mode 100644
> index 0000000..144a306
> --- /dev/null
> +++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
> @@ -0,0 +1 @@
> +piglit_include_target_api()
> diff --git 
> a/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_rende
> r_to_texture.c 
> b/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_rende
> r_to_texture.c
> new file mode 100644
> index 0000000..6a7cb02
> --- /dev/null
> +++ b/tests/spec/ext_multisampled_render_to_texture/ext_multisampled_r
> +++ ender_to_texture.c
> @@ -0,0 +1,367 @@
> +/*
> + * Copyright (c) 2015 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person 
> +obtaining a
> + * copy of this software and associated documentation files (the 
> +"Software"),
> + * to deal in the Software without restriction, including without 
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute, 
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom 
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including 
> +the next
> + * paragraph) shall be included in all copies or substantial portions 
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT 
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 
> +OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
> +OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/** \file ext_multisampled_render_to_texture.c
> + * Functional test for EXT_multisampled_render_to_texture.
> + *
> + * The test renders a ground truth image by drawing a slanted 
> +textured quad
> + * to a multisampled fbo and resolves it using a blit to a singlesampled fbo.
> + * This is textured onto the left half of the window.
> + * It then renders the same thing into an implicitly resolved fbo and 
> +textures
> + * that onto the right half of the screen. The two halfs are 
> +compared. This is
> + * repeated for another slant and different clear colors to check for 
> +possible
> + * interactions with fast clear.
> + * The test passes if the two methods yeild identical results for all 
> +image
> + * pairs.
> + *
> + */
> +
> +#include "piglit-util-gl.h"
> +
> +#define TEX_HEIGHT (8)
> +#define TEX_WIDTH (8)
> +#define FBO_HEIGHT (32)
> +#define FBO_WIDTH (32)
> +#define FB_HEIGHT (64)
> +#define FB_WIDTH (2*FB_HEIGHT)
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +	/* multisampled FBO used for ground truth req ES 3.0 */
> +	config.supports_gl_es_version = 30;
> +	config.window_visual = PIGLIT_GL_VISUAL_RGB
> +	                     | PIGLIT_GL_VISUAL_DOUBLE
> +	                     | PIGLIT_GL_VISUAL_DEPTH;
> +	config.window_width  = FB_WIDTH;
> +	config.window_height = FB_HEIGHT;
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +#define SOURCE(x) # x

That's clever.  I like it.

> +static const GLchar vshader_src[] = "#version 100\n" SOURCE(
> +	attribute vec4 piglit_vertex;
> +	attribute vec2 piglit_texcoord;
> +	varying vec2 coord_fs;
> +
> +	void main()
> +	{
> +		gl_Position =  piglit_vertex;
> +		coord_fs = piglit_texcoord;
> +	}
> +);
> +
> +static const GLchar fshader_src[] = "#version 100\n" SOURCE(
> +	precision highp float;
> +	varying vec2 coord_fs;
> +	uniform sampler2D tex;
> +
> +	void main()
> +	{
> +		gl_FragColor = texture2D(tex, coord_fs);
> +	}
> +);
> +
> +static GLuint tex_check;
> +
> +static struct {
> +	GLuint fbo;
> +	GLuint color;
> +	GLuint depth;
> +} fbo_ms, fbo_ss, fbo_impl;
> +
> +static GLuint basic_tex_prog, tex_loc;
> +
> +int result = PIGLIT_PASS;

It looks like this is only used in piglit_display, so it should be used there.

Also, the idiom in piglit is to have a bool named pass.  pass starts out set to true.  When a failure condition is detected, it is set to false.  At the end of the function that is going to generate a result,

    return pass ? PIGLIT_PASS : PIGLIT_FAIL;

or

    piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);

> +
> +static GLubyte tex_data[TEX_HEIGHT][TEX_WIDTH][3];
> +
> +static void gen_texdata(void)
> +{
> +	int x,y;
> +	for (y = 0; y < TEX_HEIGHT; ++y) {
> +		for (x = 0; x < TEX_WIDTH; ++x) {
> +			tex_data[y][x][0] = (GLubyte) (255.0f *
> +			                    ((float)x/(float)(TEX_WIDTH-1)));
> +			tex_data[y][x][1] = (GLubyte) (255.0f *
> +			                    ((float)y/(float)(TEX_HEIGHT-1)));
> +			tex_data[y][x][2] = 127;
> +		}
> +	}
> +	for (y = 0; y < TEX_HEIGHT; ++y) {
> +		for (x = 0; x < TEX_WIDTH; ++x) {
> +			if ((x^y)&1) {
> +				tex_data[y][x][0] /= 2;
> +				tex_data[y][x][1] /= 2;
> +				tex_data[y][x][2] = 64;
> +			}
> +		}
> +	}
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +	static GLfloat quad1_verts[4][4] = {
> +		{ -0.7,  -0.9, 0, 1 },
> +		{  0.9,  -0.7, 0, 1 },
> +		{ -0.9,   0.7, 0, 1 },
> +		{  0.7,   0.9, 0, 1 },
> +	};
> +
> +	static GLfloat quad2_verts[4][4] = {
> +		{ -0.9,  -0.7, 0, 1 },
> +		{  0.7,  -0.9, 0, 1 },
> +		{ -0.7,   0.9, 0, 1 },
> +		{  0.9,   0.7, 0, 1 },
> +	};
> +
> +	static const GLfloat tex_coords[4][2] = {
> +		{ 0.0, 0.0 },
> +		{ 1.0, 0.0 },
> +		{ 0.0, 1.0 },
> +		{ 1.0, 1.0 },
> +	};
> +
> +	GLfloat white[] = {1.0, 1.0, 1.0, 1.0};
> +	GLfloat gray[] = {0.5, 0.5, 0.5, 0.0};
> +
> +	/* Run the test in multiple passes with different geometry and
> +	 * different clear colors to catch possible interactions with fast
> +	 * clear.
> +	 */
> +	GLfloat *test_config[4][2] = {
> +		{ gray,  &quad1_verts[0][0] },
> +		{ gray,  &quad2_verts[0][0] },
> +		{ white, &quad1_verts[0][0] },
> +		{ white, &quad2_verts[0][0] }
> +	};

You'll be shocked and appalled by the code generated by the compiler when you don't 'static const' decorate all of this.  It's enough to make a grown man cry.

> +
> +	int i;
> +	for (i = 0; i < 4; i++) {

        for (unsigned i = 0; i < ARRAY_SIZE(test_config); i++) {

> +		GLfloat *clear_color = test_config[i][0];
> +		GLfloat *quad_verts  = test_config[i][1];
> +
> +		glClearColor(clear_color[0], clear_color[1],
> +		             clear_color[2], clear_color[3]);
> +		glUseProgram(basic_tex_prog);
> +		tex_loc = glGetUniformLocation(basic_tex_prog, "tex");
> +		glUniform1i(tex_loc, 0);

glUseProgram is already done in piglit_init, and the rest should be as well.  You can also omit setting "tex" to zero.  That is the default value for all uniforms per the GLSL spec.

> +
> +		/*** Explicit Resolve (ground truth) ***/
> +		/* Draw quad into MS renderbuffer */
> +		glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
> +		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
> +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> +		glBindTexture(GL_TEXTURE_2D, tex_check);
> +		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
> +
> +		/* Do the explicit multisample resolve */
> +		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_ms.fbo);
> +		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_ss.fbo);
> +		glBlitFramebuffer(0, 0, FBO_WIDTH, FBO_HEIGHT,
> +		                  0, 0, FBO_WIDTH, FBO_HEIGHT,
> +		                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
> +
> +		/* draw the result to the left side of the frame buffer */
> +		glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +		glViewport(0, 0, FB_WIDTH/2, FB_HEIGHT);
> +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> +		glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
> +		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);

It seems like this could be simpler... can you make fbo_ms half the width of the default framebuffer and just resolve directly from fbo_ms to the default framebuffer?

Also... instead of using 0, I think you need to use piglit_winsys_fbo.
Otherwise the test will not work properly when run with -fbo.

> +
> +		piglit_check_gl_error(GL_NO_ERROR);

                pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

> +
> +		/*** Implicit Resolve ***/
> +		/* Draw quad into MSAA texture */
> +		glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
> +		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
> +		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> +		glBindTexture(GL_TEXTURE_2D, tex_check);
> +		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
> +
> +		/* draw the result to the right side of the frame buffer */
> +		glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +		glViewport(FB_WIDTH/2, 0, FB_WIDTH/2, FB_HEIGHT);
> +
> +		glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
> +		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
> +
> +		/*** Compare the results ***/
> +		if (!piglit_probe_rect_halves_equal_rgba(0, 0, FB_WIDTH,
> +		                                         FB_HEIGHT)) {

Does the spec actually require that the results be identical?

> +			result = PIGLIT_FAIL;
> +			printf("Test failed during pass %d\n", i);
> +		}
> +
> +		piglit_present_results();

Avoid tests that overdraw previous results.  The whole point of showing the test result is to enable debugging.  If test 1 fails, tests 2 and 3 will draw over it... so why did you bother showing it in the first place?

It is easy enough in this case to make the window 4x tall and display all four results.

> +	}
> +	return result;
> +}
> +
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +	int samples = 0, samples_impl = 0, samples_expl = 0;
> +
> +	GLint max_samples;
> +
> +	piglit_require_extension("GL_EXT_multisampled_render_to_texture");
> +
> +	if (argc < 2) {
> +		fprintf(stderr, "Usage: %s <sample_count>\n", argv[0]);
> +		piglit_report_result(PIGLIT_SKIP);
> +	}
> +
> +	samples = strtoul(argv[1], NULL, 0);
> +	glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
> +	if (samples > max_samples) {
> +		piglit_report_result(PIGLIT_SKIP);
> +	}
> +
> +	/* Create primary texture */
> +	gen_texdata();
> +	glGenTextures(1, &tex_check);
> +	glActiveTexture( GL_TEXTURE0 );
> +	glBindTexture(GL_TEXTURE_2D, tex_check);
> +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0,
> +	             GL_RGB, GL_UNSIGNED_BYTE, tex_data);
> +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> +
> +	/* Create multisampled FBO for explicit resolve (ground truth) */
> +	glGenFramebuffers(1, &fbo_ms.fbo);
> +	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
> +
> +	/* depth */
> +	glGenRenderbuffers(1, &fbo_ms.depth);
> +	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.depth);
> +	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
> +	                                 GL_DEPTH_COMPONENT16,
> +	                                 FBO_WIDTH, FBO_HEIGHT);
> +	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
> +	                          GL_RENDERBUFFER, fbo_ms.depth);

Do you actually need a depth buffer?

> +
> +	/* color */
> +	glGenRenderbuffers(1, &fbo_ms.color);
> +	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.color);
> +	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGB8,
> +	                                 FBO_WIDTH, FBO_HEIGHT);
> +	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +	                          GL_RENDERBUFFER, fbo_ms.color);
> +
> +	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
> +	                          != GL_FRAMEBUFFER_COMPLETE) {
> +		printf("Multisampled framebuffer is incomplete");
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
> +	                             &samples_expl);
> +
> +	/* Create singlesampled FBO for explicit resolve (ground truth) */
> +	glGenFramebuffers(1, &fbo_ss.fbo);
> +	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ss.fbo);
> +
> +	/* color */
> +	glGenTextures(1, &fbo_ss.color);
> +	glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
> +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
> +	             GL_RGB, GL_UNSIGNED_BYTE, 0);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> +	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +	                       GL_TEXTURE_2D, fbo_ss.color, 0);
> +
> +	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
> +	                          != GL_FRAMEBUFFER_COMPLETE) {
> +		printf("Singlesampled framebuffer is incomplete");
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	/* Create FBO for implicit resolve */
> +	glGenFramebuffers(1, &fbo_impl.fbo);
> +	glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
> +
> +	/* depth */
> +	glGenRenderbuffers(1, &fbo_impl.depth);
> +	glBindRenderbuffer(GL_RENDERBUFFER, fbo_impl.depth);
> +	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
> +	                                    GL_DEPTH_COMPONENT16,
> +	                                    FBO_WIDTH, FBO_HEIGHT);
> +	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
> +	                          GL_RENDERBUFFER, fbo_impl.depth);
> +
> +	/* color */
> +	glGenTextures(1, &fbo_impl.color);
> +	glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
> +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
> +	             GL_RGB, GL_UNSIGNED_BYTE, 0);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> +	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> +	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
> +	                                     GL_COLOR_ATTACHMENT0,
> +	                                     GL_TEXTURE_2D, fbo_impl.color, 0,
> +	                                     samples);
> +
> +	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
> +	                          != GL_FRAMEBUFFER_COMPLETE) {
> +		printf("Implicitly resolved multisampled framebuffer is incomplete");
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
> +			GL_COLOR_ATTACHMENT0,
> +			GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
> +			&samples_impl);
> +
> +	glBindRenderbuffer(GL_RENDERBUFFER, 0);
> +	glBindFramebuffer(GL_FRAMEBUFFER, 0);

                                          piglit_winsys_fbo

> +
> +	glDisable(GL_CULL_FACE);
> +	glEnable(GL_DEPTH_TEST);
> +
> +	/* Test that we get the same number of samples for the two methods 
> +*/
> +
> +	if (samples_impl != samples_expl) {
> +		printf("samples_expl: %d, samples_impl: %d\n",
> +		        samples_expl, samples_impl);
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	/* create basic texturing shader */
> +	basic_tex_prog = piglit_build_simple_program(vshader_src,
> +	                                             fshader_src);
> +	glUseProgram(basic_tex_prog);
> +
> +	if (!piglit_check_gl_error(GL_NO_ERROR)) {
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +}



More information about the Piglit mailing list