Hi,

On Thursday, September 18, 2014 03:56:11 Roland Scheidegger wrote:
> I agree it is something which would be nice to have in mesa, however I'm
> not really a big proponent of implementing some half-baked bogus mess
> extension, which is further more completely different to what the only
> available implementation actually does.
Me neither, I initially thought that it's just much more clear what to do.

> Just to make this clear, are you saying that blob really clamps all
> float depth values to [0,1] when
> - using teximage2d
> - writing depth from fragment shader
> - using interpolated depth (with depth_clamp enabled maybe?)

I have never tried the teximage2d claims.

But I have tried with and without writing the gl_FragDepth.
I have now rechecked this on nvidia and the amd blob.

I have to correct the claim somehow - I previously probably only tested 
gl_FragDepth
clamping with depthrange set to [0, 1]. But actual behavior is even nicer, as
NVidia does not make any difference between the two texture
formats in its behavior. Everything is clamped to be within min(zNear, zFar)
and max(zNear, zFar) of glDepthRangedNV(zNear, zFar).
It does not matter if you write the gl_FragmentDepth or use the fixed function
depth processing. And this is independent of the depth texture format
being GL_DEPTH_COMPONENT32F or GL_DEPTH_COMPONENT32F_NV.

> So I think I'm missing something why can you even clear the depth buffer
> to a value outside [0,1] then?
The fixed function depth values are just routed through and they utilize
in any case the whole range between near and far.
Or, I may not get your question right ...

> In any case, I'm not really against this, though I'm not really the
> right person to judge this in any case. I think though at the very least
> there should probably be big warning comments in the code mentioning it
> doesn't actually implement what the extension says and why. It would
> probably be better though if nvidia would fix up their extension spec
> (or failing that, someone could make some proper non-vendor extension).
> I wonder what AMD is doing on their blob. I suspect though they just do
> the different non-clamping entry points...
It took some work to convince piglit to think centos 6 is a recent enough 
system.
I have now within piglit also done a test program to explore the
behavior of the implementations. That's attached.
So, it looks like the AMD blob changes it's behavior based on the
internal format. The _NV variants behave the same like the nvidia
driver treats them. The ARB internal formats, behave like if the
glDepthRangedNV call had behaved like glDepthRange.
There is a define in the attached test that makes either the amd or the
nvidia variant succeed.

The nvidia behavior is more like the last addition to the NV_ spec that
tells that there should be no difference between the non _NV float formats.
The AMD blob more tries to model one of the contradicting difference in the
specs.

The nvidia behavior looks like the least intrusive for the driver.
You get the GL standard behavior in the case of the non NV API entry points
since you are not able to go beyond [0, 1] in the depth range.
But if you manage to get near and far values beyond [0, 1] into the driver
by using glDepthRangedNV, you get everything clamped to these.

Greetings

Mathias
/*
 * Copyright Mathias Fröhlich <mathias.froehl...@web.de>
 *
 * 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.
 *
 * Authors:
 *    Mathias Fröhlich <mathias.froehl...@web.de>
 */

/** @file depth-range-nv.c
 *
 * Basic test for NV_depth_buffer_float not clamping the near and far values.
 */

#include "piglit-util-gl.h"

PIGLIT_GL_TEST_CONFIG_BEGIN

	config.supports_gl_compat_version = 20;

	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_DEPTH;

PIGLIT_GL_TEST_CONFIG_END

#define ELEMENTS(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
#define MIN( A, B )   ( (A) < (B) ? (A) : (B) )
#define MAX( A, B )   ( (A) > (B) ? (A) : (B) )

void
piglit_init(int argc, char **argv)
{
	piglit_require_extension("GL_NV_depth_buffer_float");
	piglit_require_extension("GL_EXT_framebuffer_object");
	piglit_require_extension("GL_EXT_framebuffer_blit");

	piglit_require_GLSL();

	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
}

static const char *frag_text =
"void main() \n"
"{ \n"
"	gl_FragColor = vec4(1.0);\n"
"	gl_FragDepth = gl_FragCoord.z;\n"
"} \n";

GLboolean
is_nv_float_depth(GLenum type)
{
	switch (type) {
	case GL_DEPTH_COMPONENT32F_NV:
	case GL_DEPTH32F_STENCIL8_NV:
		return GL_TRUE;
	default:
		return GL_FALSE;
	}
}

GLboolean
is_float_depth(GLenum type)
{
	switch (type) {
	case GL_DEPTH_COMPONENT32F_NV:
	case GL_DEPTH32F_STENCIL8_NV:
	case GL_DEPTH_COMPONENT32F:
	case GL_DEPTH32F_STENCIL8:
		return GL_TRUE;
	default:
		return GL_FALSE;
	}
}

void
quad(float base_x, float base_y, float z)
{
	glBegin(GL_QUADS);
	glVertex3f(base_x,	base_y,	     z);
	glVertex3f(base_x + 10, base_y,	     z);
	glVertex3f(base_x + 10, base_y + 10, z);
	glVertex3f(base_x,	base_y + 10, z);
	glEnd();
}

/* #define AMD_DRIVER */

GLdouble
expected_depth(GLenum type, GLdouble z, GLdouble n, GLdouble f)
{
	GLdouble zMin;
	GLdouble zMax;

#ifdef AMD_DRIVER
	if (!is_nv_float_depth(type))
#else
	if (!is_float_depth(type))
#endif
	{
		n = MAX(0, n);
		n = MIN(1, n);
		f = MAX(0, f);
		f = MIN(1, f);
	}

	zMin = MIN(n, f);
	zMax = MAX(n, f);

	z = z*0.5*(n - f) + 0.5*(n + f);
	z = MAX(zMin, z);
	z = MIN(zMax, z);

	return z;
}

GLdouble
expected_clear_depth(GLenum type, GLdouble c)
{
#ifdef AMD_DRIVER
	if (!is_nv_float_depth(type))
#else
	if (!is_float_depth(type))
#endif
	{
		 c = MAX(0, c);
		 c = MIN(1, c);
	}

	return c;
}

GLboolean
do_display(GLenum type, GLdouble n, GLdouble f, GLdouble c, GLboolean depth_clamp)
{
	GLboolean pass = GL_TRUE;
	GLenum status;
	GLuint fb, cb, db;

	if (type == GL_DEPTH_COMPONENT32F)
		printf("TYPE = GL_DEPTH_COMPONENT32F, ");
	else if (type == GL_DEPTH_COMPONENT32F_NV)
		printf("TYPE = GL_DEPTH_COMPONENT32F_NV, ");
	else if (type == GL_DEPTH32F_STENCIL8)
		printf("TYPE = GL_DEPTH32F_STENCIL8, ");
	else if (type == GL_DEPTH32F_STENCIL8_NV)
		printf("TYPE = GL_DEPTH32F_STENCIL8_NV, ");
	else
		printf("TYPE = 0x%X, ", type);

	printf(" DepthRange(%f, %f), depth_clamp = %d\n", n, f, depth_clamp);

	glGenRenderbuffers(1, &cb);
	glBindRenderbuffer(GL_RENDERBUFFER, cb);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, piglit_width, piglit_height);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glGenRenderbuffers(1, &db);
	glBindRenderbuffer(GL_RENDERBUFFER, db);
	glRenderbufferStorage(GL_RENDERBUFFER, type, piglit_width, piglit_height);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glGenFramebuffers(1, &fb);
	glBindFramebuffer(GL_FRAMEBUFFER, fb);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cb);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, db);

	status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if (status != GL_FRAMEBUFFER_COMPLETE) {
		printf("FBO incomplete status 0x%X\n", status);
		piglit_report_result(PIGLIT_FAIL);
	}

	glClearDepthdNV(c);
	glClear(GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_ALWAYS);
	if (depth_clamp)
		glEnable(GL_DEPTH_CLAMP);
	else
		glDisable(GL_DEPTH_CLAMP);

	glDepthRangedNV(n, f);
	quad(10, 10, -1.5);
	quad(10, 30, -1.0);
	quad(10, 50, -0.5);
	quad(10, 70, 0);
	quad(10, 90, 0.5);
	quad(10, 110, 1.0);
	quad(10, 130, 1.5);

	/* The clear value */
	pass = piglit_probe_pixel_depth(5, 5, expected_clear_depth(type, c)) && pass;

	/* The few patches drawn above */
	if (depth_clamp)
		pass = piglit_probe_pixel_depth(15, 15, expected_depth(type, -1.5, n, f)) && pass;
	else
		pass = piglit_probe_pixel_depth(15, 15, expected_clear_depth(type, c)) && pass;
	pass = piglit_probe_pixel_depth(15, 35, expected_depth(type, -1.0, n, f)) && pass;
	pass = piglit_probe_pixel_depth(15, 55, expected_depth(type, -0.5, n, f)) && pass;
	pass = piglit_probe_pixel_depth(15, 75, expected_depth(type, 0, n, f)) && pass;
	pass = piglit_probe_pixel_depth(15, 95, expected_depth(type, 0.5, n, f)) && pass;
	pass = piglit_probe_pixel_depth(15, 115, expected_depth(type, 1.0, n, f)) && pass;
	if (depth_clamp)
		pass = piglit_probe_pixel_depth(15, 135, expected_depth(type, 1.5, n, f)) && pass;
	else
		pass = piglit_probe_pixel_depth(15, 135, expected_clear_depth(type, c)) && pass;

	/* copy the result to the back buffer */

	/* set viewport to window size */
	glViewport(0, 0, piglit_width, piglit_height);

	glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
	glBlitFramebuffer(0, 0, piglit_width, piglit_height,
			  0, 0, piglit_width, piglit_height,
			  GL_COLOR_BUFFER_BIT, GL_NEAREST);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glDeleteFramebuffers(1, &fb);
	glDeleteRenderbuffers(1, &cb);
	glDeleteRenderbuffers(1, &db);

	piglit_present_results();

	return pass;
}

GLboolean
do_loops(GLenum type)
{
	GLboolean pass = GL_TRUE;
	GLint ri, ci, dc;
	GLint maxdc = 1;
	GLdouble ranges[][2] = {
		{ 0, 1 },
		{ -1, 1 },
		{ -1, 0 },
		{ -10, 5 },
		{ 0.5, 0.75 }
	};
	GLdouble clears[][2] = {
		{ 0, 1 },
		{ 0.5, 0.5 },
		{ 1, 0 }
	};

	if (piglit_is_extension_supported("GL_ARB_depth_clamp"))
		maxdc += 1;

	for (ri = 0; ri < ELEMENTS(ranges); ++ri) {
		for (ci = 0; ci < ELEMENTS(clears); ++ci) {
			for (dc = 0; dc < maxdc; ++dc) {
				GLdouble c = clears[ci][0]*ranges[ri][0] + clears[ci][1]*ranges[ri][1];
				pass = do_display(type, ranges[ri][0], ranges[ri][1], c, dc) && pass;
				pass = do_display(type, ranges[ri][1], ranges[ri][0], c, dc) && pass;
			}
		}
	}

	return pass;
}

GLboolean
do_buffers(void)
{
	GLboolean pass = GL_TRUE;
	GLint bi;
	GLenum types[] = {
		GL_DEPTH_COMPONENT16,
		GL_DEPTH_COMPONENT24,
		GL_DEPTH_COMPONENT32F,
		GL_DEPTH_COMPONENT32F_NV,
		GL_DEPTH32F_STENCIL8,
		GL_DEPTH32F_STENCIL8_NV
	};

	for (bi = 0; bi < ELEMENTS(types); ++bi) {
		pass = do_loops(types[bi]) && pass;
	}

	return pass;
}

enum piglit_result
piglit_display(void)
{
	GLboolean pass = GL_TRUE;
	GLint prog;

	pass = do_buffers() && pass;

	prog = piglit_build_simple_program(NULL, frag_text);
	glUseProgram(prog);

	pass = do_buffers() && pass;

	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to